Skip to content

Commit 0b4d47d

Browse files
authored
Add Nickname Support + Cleanup (#72)
2 parents 90c41ac + 1ab64fb commit 0b4d47d

14 files changed

+207
-157
lines changed

.env.development

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
SUPABASE_AUTH_DISCORD_CLIENT_ID="1234567890"
2-
SUPABASE_AUTH_DISCORD_SECRET="abcdefghijklmnopqrstuvwxyz"
31
POSTGRES_URL="postgresql://postgres:[email protected]:54322/postgres"
42
NEXT_PUBLIC_SUPABASE_URL="http://127.0.0.1:54321"
53
NEXT_PUBLIC_SUPABASE_REDIRECT_URL="http://localhost:3000/auth/callback"

.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
SUPABASE_AUTH_DISCORD_CLIENT_ID="1234567890"
22
SUPABASE_AUTH_DISCORD_SECRET="some_random_key"
33
NEXT_PUBLIC_SUPABASE_ANON_KEY="some_random_key, found by running supabase start or supabase status"
4+
SUPABASE_SERVICE_KEY="some_random_key, found by running supabase start or supabase status"
45
JWT_SECRET="super-secret-jwt-token-with-at-least-32-characters-long"

.env.production

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
POSTGRES_URL="postgresql://postgres:[email protected]:54322/postgres"
2+
NEXT_PUBLIC_SUPABASE_URL="http://127.0.0.1:54321"
3+
NEXT_PUBLIC_SUPABASE_REDIRECT_URL="http://localhost:3000/auth/callback"

SETUP.md

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Copy the following output values to your environment file:
7777
`anon key` to `NEXT_PUBLIC_SUPABASE_ANON_KEY`
7878
`API URL` to `NEXT_PUBLIC_SUPABASE_URL`
7979
`JWT secret` to `JWT_SECRET`
80+
`service_role key` to `SUPABASE_SERVICE_KEY`
8081

8182
To stop running supabase, type `supabase stop` into your terminal.
8283

app/auth/callback/route.ts

+53-37
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
11
import { createClient } from "@/lib/database/server";
2+
import { createServiceClient } from "@/lib/database/service";
23
import { NextResponse } from "next/server";
34

4-
interface ServerData {
5-
id: string;
6-
name: string;
7-
icon: string;
8-
owner: boolean;
9-
permissions: number;
10-
permissions_new: string;
11-
features: any[];
5+
interface DiscordGuildMemberResponse {
6+
message?: string;
7+
code?: number;
8+
avatar: string | null;
9+
banner: string | null;
10+
communication_disabled_until: string | null;
11+
flags: number;
12+
joined_at: string;
13+
nick: string;
14+
pending: boolean;
15+
premium_since: string | null;
16+
roles: string[];
17+
unusual_dm_activity_until: string;
18+
user: {
19+
id: string;
20+
username: string;
21+
avatar: string;
22+
discriminator: string;
23+
public_flags: number;
24+
flags: number;
25+
banner: string | null;
26+
accent_color: string | null;
27+
global_name: string;
28+
avatar_decoration_data: string;
29+
banner_color: string;
30+
clan: string;
31+
};
32+
mute: boolean;
33+
deaf: boolean;
34+
bio: string;
1235
}
1336

1437
export async function GET(request: Request) {
@@ -18,42 +41,35 @@ export async function GET(request: Request) {
1841

1942
if (code) {
2043
const supabase = createClient();
21-
await supabase.auth.exchangeCodeForSession(code);
44+
const {
45+
data: { session, user },
46+
} = await supabase.auth.exchangeCodeForSession(code);
2247

23-
const { data } = await supabase.auth.getSession();
24-
25-
if (!data.session) {
26-
return NextResponse.redirect(origin);
48+
if (!session) {
49+
return NextResponse.redirect(`${origin}/403`);
2750
}
2851

2952
const headers = new Headers();
30-
headers.append(
31-
"Authorization",
32-
`Bearer ${data.session?.provider_token}`
33-
);
34-
35-
let servers: ServerData[];
36-
try {
37-
const userServers = await fetch(
38-
`https://discord.com/api/users/@me/guilds`,
39-
{ headers }
40-
);
41-
servers = await userServers.json();
42-
} catch (error) {
43-
console.error("Error fetching user servers:", error);
44-
return NextResponse.redirect(origin);
45-
}
53+
headers.append("Authorization", `Bearer ${session.provider_token}`);
54+
55+
const servers: DiscordGuildMemberResponse = await fetch(
56+
`https://discord.com/api/users/@me/guilds/408711970305474560/member`,
57+
{ headers }
58+
).then((res) => res.json());
4659

47-
const serverId = "408711970305474560";
48-
const serverIsInList = servers.some((server) => server.id === serverId);
60+
if (!servers || servers?.code) {
61+
const serviceClient = createServiceClient();
4962

50-
if (serverIsInList) {
51-
// YETI is in the list of servers
52-
return NextResponse.redirect(`${origin}/profile`);
53-
} else {
54-
// YETI is not in the list of servers
63+
await serviceClient.auth.admin.deleteUser(user.id);
5564
await supabase.auth.signOut();
56-
return NextResponse.redirect(origin);
65+
return NextResponse.redirect(`${origin}/403`);
5766
}
67+
68+
await supabase
69+
.from("profile")
70+
.update({ nick: servers.nick })
71+
.eq("id", user.id);
72+
73+
return NextResponse.redirect(`${origin}/profile`);
5874
}
5975
}

drizzle.config.ts

-14
This file was deleted.

lib/auth-actions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export async function signIn() {
1010
provider: "discord",
1111
options: {
1212
redirectTo: process.env.NEXT_PUBLIC_SUPABASE_REDIRECT_URL,
13-
scopes: "guilds",
13+
scopes: "guilds.members.read",
1414
},
1515
});
1616

lib/database/schema.ts

-85
This file was deleted.

lib/database/server.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createServerClient, type CookieOptions } from "@supabase/ssr";
1+
import { createServerClient } from "@supabase/ssr";
22
import { cookies } from "next/headers";
33

44
export function createClient() {

lib/database/service.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createClient } from "@supabase/supabase-js";
2+
3+
/**
4+
* SHOULD ONLY EVER BE USED ON SERVER
5+
*/
6+
export function createServiceClient() {
7+
return createClient(
8+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
9+
process.env.SUPABASE_SERVICE_KEY!,
10+
{
11+
auth: {
12+
persistSession: false,
13+
autoRefreshToken: false,
14+
detectSessionInUrl: false,
15+
},
16+
}
17+
);
18+
}

supabase/migrations/20240725022411_init.sql

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
11
create type public.app_permission as enum ('admin.access', 'standform.submit');
22

3-
create type public.app_role as enum ('admin', 'yeti-member', 'external');
3+
create type public.app_role as enum ('admin', 'yeti-member');
44

5-
-- PROFILES
6-
create table public.profiles (
5+
-- profile
6+
create table public.profile (
77
id uuid not null references auth.users on delete cascade,
8+
nick varchar(32),
89
primary key (id)
910
);
1011

1112
-- USER ROLES
1213
create table public.user_roles (
1314
id bigint generated by default as identity primary key,
14-
user_id uuid references public.profiles on delete cascade not null,
15+
user_id uuid references public.profile on delete cascade not null,
1516
role app_role not null,
16-
unique (user_id, role)
17+
unique (user_id)
1718
);
1819

20+
create index on public.user_roles using btree (user_id);
21+
1922

2023
create function public.handle_new_user()
2124
returns trigger
2225
language plpgsql
2326
security definer set search_path = ''
2427
as $$
2528
begin
26-
insert into public.profiles (id) values (new.id);
27-
insert into public.user_roles (user_id, role) values (new.id, 'external');
29+
insert into public.profile (id) values (new.id);
30+
insert into public.user_roles (user_id, role) values (new.id, 'yeti-member');
2831
return new;
2932
end;
3033
$$;
@@ -65,11 +68,11 @@ begin
6568
end;
6669
$$ language plpgsql stable security definer set search_path = '';
6770

68-
alter table public.profiles enable row level security;
71+
alter table public.profile enable row level security;
6972
alter table public.role_permissions enable row level security;
7073
alter table public.user_roles enable row level security;
7174

72-
create policy "Allow logged-in read access" on public.profiles for insert with check ( auth.role() = 'authenticated' );
73-
create policy "Allow individual update access" on public.profiles for update using ( auth.uid() = id );
75+
create policy "Allow logged-in read access" on public.profile for select using ( (SELECT auth.role()) = 'authenticated' );
76+
create policy "Allow individual update access" on public.profile for update using ( (SELECT auth.uid()) = id );
7477
create policy "Allow admin role access" on public.user_roles for all using ( (SELECT authorize('admin.access')));
75-
78+
create policy "Allow admin access" on public.role_permissions for all using ( (SELECT authorize('admin.access')));

supabase/migrations/20240725023113_auth_hook.sql

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
create or replace function public.custom_access_token_hook(event jsonb)
33
returns jsonb
44
language plpgsql
5+
set search_path = ''
56
stable
67
as $$
78
declare

0 commit comments

Comments
 (0)