Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ FRONTEND_URL=http://localhost:5173
# Add a random string here
# In order to generate one, you may use this command: openssl rand -base64 32
BETTER_AUTH_SECRET=

GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=

DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
16 changes: 15 additions & 1 deletion backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,21 @@ brew install postgresql@18

### Setting the environment variables

Copy the [.env.example](./.env.example) and replace the `DATABASE_URL` if needed.
Start by copying the [.env.example](./.env.example) to `.env`:

```sh
cd backend
cp .env.example .env
```

Proceed to do the following:

- Check whether the `DATABASE_URL` needs to be updated for the deployment
- Make sure the URLs for the frontend and backend are correct
- Create and insert the GitHub client ID and client secret:
- This can be done by creating an OAuth application in [GitHub's Developer settings -> OAuth Apps](https://github.com/settings/developers)
- Create and insert the Discord client ID and client secret:
- This can be done by creating an application in [Discord's Developer Portal](https://discord.com/developers/applications)

### Downloading the book dataset

Expand Down
10 changes: 10 additions & 0 deletions backend/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,15 @@ export const auth = betterAuth({
},
},
},
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID ?? "",
clientSecret: process.env.GITHUB_CLIENT_SECRET ?? "",
},
discord: {
clientId: process.env.DISCORD_CLIENT_ID ?? "",
clientSecret: process.env.DISCORD_CLIENT_SECRET ?? "",
},
},
trustedOrigins: [process.env.FRONTEND_URL ?? "http://localhost:5173"],
});
2 changes: 2 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
VITE_APP_URL=http://localhost:5173

# Must be changed to http://it2810-37.idi.ntnu.no:3001/ for production
VITE_API_URL = http://localhost:3001
10 changes: 10 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ cd frontend
pnpm i # or: pnpm install
```

Set up environment variables:

```
cd frontend
cp .env.example .env
```

Make sure `VITE_APP_URL` matches the frontend URL.
We need this URL to use as the callback URL for Social OAuth logins - otherwise we will be redirected to the backend at port `3001`, which is not what we want.

Run the application:

```sh
Expand Down
32 changes: 31 additions & 1 deletion frontend/app/routes/login.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { Link, useNavigate } from "react-router";
import { Link, Navigate, useNavigate } from "react-router";
import { useForm } from "@tanstack/react-form";
import { z } from "zod";
import { authClient } from "~/api/auth";
Expand All @@ -21,6 +21,7 @@ import {
import { Input } from "~/components/ui/Input";
import { Spinner } from "~/components/ui/Spinner";
import { toast } from "~/components/ui/Toast";
import { SiDiscord, SiGithub } from "@icons-pack/react-simple-icons";

const formSchema = z.object({
email: z.email("Enter a valid email address."),
Expand All @@ -34,6 +35,7 @@ export function meta() {
export default function LoginPage() {
const navigate = useNavigate();
const [serverError, setServerError] = useState<string | null>(null);
const { data: session } = authClient.useSession();

const form = useForm({
defaultValues: {
Expand Down Expand Up @@ -61,6 +63,10 @@ export default function LoginPage() {
},
});

if (session) {
return <Navigate to="/" />;
}

return (
<main className="grid place-items-center px-4 py-20">
<Card className="w-full max-w-sm">
Expand Down Expand Up @@ -149,6 +155,30 @@ export default function LoginPage() {
</Button>
)}
</form.Subscribe>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "github",
callbackURL: `${import.meta.env.VITE_APP_URL ?? window.location.origin}${import.meta.env.BASE_URL}`,
})
}
variant="outline"
>
<SiGithub className="mr-2 h-4 w-4" />
Log in with GitHub
</Button>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "discord",
callbackURL: `${import.meta.env.VITE_APP_URL ?? window.location.origin}${import.meta.env.BASE_URL}`,
})
}
variant="outline"
>
<SiDiscord className="mr-2 h-4 w-4" />
Log in with Discord
</Button>
<p className="text-muted-foreground">
Don't have an account?{" "}
<Link to="/signup" className="text-primary underline">
Expand Down
32 changes: 31 additions & 1 deletion frontend/app/routes/signup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { Link, useNavigate } from "react-router";
import { Link, Navigate, useNavigate } from "react-router";
import { useForm } from "@tanstack/react-form";
import { z } from "zod";
import { authClient } from "~/api/auth";
Expand All @@ -22,6 +22,7 @@ import {
import { Input } from "~/components/ui/Input";
import { Spinner } from "~/components/ui/Spinner";
import { toast } from "~/components/ui/Toast";
import { SiDiscord, SiGithub } from "@icons-pack/react-simple-icons";

// Matches better-auth's default minPasswordLength.
const MIN_PASSWORD_LENGTH = 8;
Expand All @@ -45,6 +46,7 @@ export function meta() {
export default function SignupPage() {
const navigate = useNavigate();
const [serverError, setServerError] = useState<string | null>(null);
const { data: session } = authClient.useSession();

const form = useForm({
defaultValues: {
Expand Down Expand Up @@ -80,6 +82,10 @@ export default function SignupPage() {
},
});

if (session) {
return <Navigate to="/" />;
}

return (
<main className="grid place-items-center px-4 py-20">
<Card className="w-full max-w-sm">
Expand Down Expand Up @@ -230,6 +236,30 @@ export default function SignupPage() {
</Button>
)}
</form.Subscribe>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "github",
callbackURL: `${import.meta.env.VITE_APP_URL ?? window.location.origin}${import.meta.env.BASE_URL}`,
})
}
variant="outline"
>
<SiGithub className="mr-2 h-4 w-4" />
Sign up with GitHub
</Button>
<Button
onClick={() =>
void authClient.signIn.social({
provider: "discord",
callbackURL: `${import.meta.env.VITE_APP_URL ?? window.location.origin}${import.meta.env.BASE_URL}`,
})
}
variant="outline"
>
<SiDiscord className="mr-2 h-4 w-4" />
Sign up with Discord
</Button>
<p className="text-muted-foreground">
Already have an account?{" "}
<Link to="/login" className="text-primary underline">
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@apollo/client": "^4.3.1",
"@base-ui/react": "^1.8.0",
"@fontsource-variable/inter": "^5.3.0",
"@icons-pack/react-simple-icons": "^13.15.1",
"@react-router/node": "^8.4.0",
"@react-router/serve": "^8.4.0",
"@tailwindcss/vite": "^4.3.3",
Expand Down
12 changes: 12 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.