Skip to content

Commit 3f925ba

Browse files
committed
configuring sentry + instrumenting backend
1 parent 693018f commit 3f925ba

40 files changed

+2741
-557
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SENTRY_DSN=
2+
NEXT_PUBLIC_SENTRY_DSN=
3+
SENTRY_AUTH_TOKEN=

.env.sentry-build-plugin.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# DO NOT commit this file to your repository!
2+
# The SENTRY_AUTH_TOKEN variable is picked up by the Sentry Build Plugin.
3+
# It's used for authentication when uploading source maps.
4+
# You can also set this env variable in your own `.env` files and remove this file.
5+
SENTRY_AUTH_TOKEN=

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@ yarn-error.log*
3636
next-env.d.ts
3737

3838
sqlite.db
39+
40+
# Sentry Config File
41+
.env.sentry-build-plugin
42+
43+
# Environment variables
44+
.env

app/(auth)/actions.ts

Lines changed: 0 additions & 99 deletions
This file was deleted.

app/(auth)/sign-in/page.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,26 @@ import { Label } from "../../_components/ui/label";
1313
import { Separator } from "../../_components/ui/separator";
1414
import { Button } from "../../_components/ui/button";
1515
import { useState } from "react";
16-
import { signIn } from "../actions";
16+
import { useRouter } from "next/navigation";
1717

1818
export default function SignIn() {
1919
const [error, setError] = useState<string>();
20+
const router = useRouter();
21+
2022
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
2123
event.preventDefault();
2224

2325
const formData = new FormData(event.currentTarget);
24-
const res = await signIn(formData);
25-
if (res && res.error) {
26-
setError(res.error);
26+
const res = await fetch("/api/auth/sign-in", {
27+
method: "POST",
28+
body: formData,
29+
});
30+
31+
if (res.ok) {
32+
router.push("/");
33+
} else {
34+
const { error } = await res.json();
35+
setError(error);
2736
}
2837
};
2938

app/(auth)/sign-up/page.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
"use client";
22

33
import Link from "next/link";
4+
import { useRouter } from "next/navigation";
5+
import { useState } from "react";
6+
7+
import { Button } from "../../_components/ui/button";
48
import {
59
Card,
610
CardContent,
@@ -11,12 +15,11 @@ import {
1115
import { Input } from "../../_components/ui/input";
1216
import { Label } from "../../_components/ui/label";
1317
import { Separator } from "../../_components/ui/separator";
14-
import { Button } from "../../_components/ui/button";
15-
import { signUp } from "../actions";
16-
import { useState } from "react";
1718

1819
export default function SignUp() {
1920
const [error, setError] = useState<string>();
21+
const router = useRouter();
22+
2023
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
2124
event.preventDefault();
2225

@@ -30,9 +33,15 @@ export default function SignUp() {
3033
return;
3134
}
3235

33-
const res = await signUp(formData);
34-
if (res && res.error) {
35-
setError(res.error);
36+
const res = await fetch("/api/auth/sign-up", {
37+
method: "POST",
38+
body: formData,
39+
});
40+
if (res.ok) {
41+
router.push("/");
42+
} else {
43+
const { error } = await res.json();
44+
setError(error);
3645
}
3746
};
3847

app/_components/ui/user-menu.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { signOut } from "@/app/(auth)/actions";
3+
import { useRouter } from "next/navigation";
44
import { Avatar, AvatarFallback } from "./avatar";
55
import {
66
DropdownMenu,
@@ -10,6 +10,17 @@ import {
1010
} from "./dropdown-menu";
1111

1212
export function UserMenu() {
13+
const router = useRouter();
14+
15+
const handleSignOut = async () => {
16+
const res = await fetch("/api/auth/sign-out", {
17+
method: "POST",
18+
});
19+
if (res.ok) {
20+
router.push("/sign-in");
21+
}
22+
};
23+
1324
return (
1425
<DropdownMenu>
1526
<DropdownMenuTrigger>
@@ -18,7 +29,10 @@ export function UserMenu() {
1829
</Avatar>
1930
</DropdownMenuTrigger>
2031
<DropdownMenuContent>
21-
<DropdownMenuItem className="cursor-pointer" onClick={() => signOut()}>
32+
<DropdownMenuItem
33+
className="cursor-pointer"
34+
onClick={() => handleSignOut()}
35+
>
2236
Sign out
2337
</DropdownMenuItem>
2438
</DropdownMenuContent>

app/actions.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

app/add-todo.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
"use client";
22

33
import { Plus } from "lucide-react";
4-
import { Button } from "./_components/ui/button";
5-
import { Input } from "./_components/ui/input";
6-
import { createTodo } from "./actions";
4+
import { useRouter } from "next/navigation";
75
import { useRef } from "react";
86
import { toast } from "sonner";
97

8+
import { Button } from "./_components/ui/button";
9+
import { Input } from "./_components/ui/input";
10+
1011
export function CreateTodo() {
1112
const inputRef = useRef<HTMLInputElement>(null);
13+
const router = useRouter();
1214

1315
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
1416
event.preventDefault();
1517

1618
const formData = new FormData(event.currentTarget);
17-
const res = await createTodo(formData);
19+
const res = await fetch("/api/todos", { method: "PUT", body: formData });
1820

19-
if (res) {
20-
if (res.error) {
21-
toast.error(res.error);
22-
} else if (res.success) {
23-
toast.success("Todo created!");
21+
if (res.ok) {
22+
toast.success("Todo created!");
23+
router.refresh();
24+
} else {
25+
const { error } = await res.json();
26+
toast.error(error);
27+
if (res.status === 401) {
28+
router.push("/sign-in");
2429
}
2530
}
2631

app/api/auth/sign-in/route.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { captureException } from "@sentry/nextjs";
2+
import { cookies } from "next/headers";
3+
4+
import { AuthenticationError } from "@/src/entities/errors/auth";
5+
import { InputParseError } from "@/src/entities/errors/common";
6+
import { Cookie } from "@/src/entities/models/cookie";
7+
import { signInController } from "@/src/interface-adapters/controllers/auth/sign-in.controller";
8+
9+
export async function POST(request: Request) {
10+
const formData = await request.formData();
11+
const username = formData.get("username")?.toString();
12+
const password = formData.get("password")?.toString();
13+
14+
let sessionCookie: Cookie;
15+
try {
16+
sessionCookie = await signInController({ username, password });
17+
} catch (err) {
18+
if (err instanceof InputParseError || err instanceof AuthenticationError) {
19+
return Response.json(
20+
{ error: "Incorrect username or password" },
21+
{ status: 400 },
22+
);
23+
}
24+
25+
captureException(err);
26+
return Response.json(
27+
{
28+
error:
29+
"An error happened. The developers have been notified. Please try again later.",
30+
},
31+
{ status: 500 },
32+
);
33+
}
34+
35+
cookies().set(
36+
sessionCookie.name,
37+
sessionCookie.value,
38+
sessionCookie.attributes,
39+
);
40+
41+
return new Response();
42+
}

0 commit comments

Comments
 (0)