feat(frontend): log in with Discord

This commit is contained in:
Sam 2022-09-16 00:49:04 +02:00
parent e4d028bbad
commit 4a8e1bb54f
8 changed files with 158 additions and 3 deletions

View file

@ -0,0 +1,74 @@
import { useEffect } from "react";
import { useRouter } from "next/router";
import { GetServerSideProps } from "next";
import { useRecoilState } from "recoil";
import fetchAPI from "../../lib/fetch";
import { userState } from "../../lib/state";
import { MeUser } from "../../lib/types";
interface CallbackResponse {
has_account: boolean;
token?: string;
user?: MeUser;
discord?: string;
ticket?: string;
require_invite?: boolean;
}
interface State {
hasAccount: boolean;
isLoading: boolean;
token?: string;
user?: MeUser;
discord?: string;
ticket?: string;
error?: any;
}
export default function Discord(props: State) {
const router = useRouter();
const [user, setUser] = useRecoilState(userState);
useEffect(() => {
// we got a token + user, save it and return to the home page
if (props.token) {
localStorage.setItem("pronouns-token", props.token);
setUser(props.user!);
router.push("/");
}
}, [props.token, props.user, setUser, router]);
return <>wow such login</>;
}
export const getServerSideProps: GetServerSideProps<State> = async (
context
) => {
try {
const resp = await fetchAPI<CallbackResponse>(
"/auth/discord/callback",
"POST",
{
callback_domain: process.env.DOMAIN,
code: context.query.code,
state: context.query.state,
}
);
return {
props: {
hasAccount: resp.has_account,
isLoading: false,
token: resp.token,
user: resp.user,
discord: resp.discord || null,
ticket: resp.ticket || null,
},
};
} catch (e) {
return { props: { error: e } };
}
};

View file

@ -0,0 +1,41 @@
import { GetServerSideProps } from "next";
import { useRouter } from "next/router";
import { useRecoilValue } from "recoil";
import Head from "next/head";
import fetchAPI from "../../lib/fetch";
import { userState } from "../../lib/state";
interface URLsResponse {
discord: string;
}
export default function Login({ urls }: { urls: URLsResponse }) {
const router = useRouter();
if (useRecoilValue(userState) !== null) {
router.push("/");
}
return (
<>
<Head>
<title key="title">Login - pronouns.cc</title>
</Head>
<a href={urls.discord}>Login with Discord</a>
</>
);
}
export const getServerSideProps: GetServerSideProps = async (context) => {
try {
const urls = await fetchAPI<URLsResponse>("/auth/urls", "POST", {
callback_domain: process.env.DOMAIN,
});
return { props: { urls } };
} catch (e) {
console.log(e);
return { notFound: true };
}
};

View file

@ -6,23 +6,45 @@ import FieldCard from "../../../components/FieldCard";
import Card from "../../../components/Card";
import ReactMarkdown from "react-markdown";
import Image from "next/image";
import { userState } from "../../../lib/state";
import { useRecoilValue } from "recoil";
import Link from "next/link";
interface Props {
user: User;
}
export default function Index({ user }: Props) {
const isMeUser = useRecoilValue(userState)?.id === user.id;
return (
<>
<Head>
<title key="title">@{user.username} - pronouns.cc</title>
</Head>
{isMeUser && (
<div className="lg:w-1/3 mx-auto bg-slate-100 dark:bg-slate-700 shadow rounded-md p-2">
<span>
You are currently viewing your{" "}
<span className="font-bold">public</span> profile.
</span>
<br />
<Link
href="/edit/profile"
className="hover:underline text-sky-500 dark:text-sky-400"
>
Edit your profile
</Link>
</div>
)}
<div className="container mx-auto">
<div className="flex flex-col m-2 p-2 lg:flex-row justify-center lg:justify-start items-center space-y-4 lg:space-y-0 lg:space-x-16 lg:items-start border-b border-slate-200 dark:border-slate-700">
{user.avatar_url && (
<Image
<img
className="max-w-xs rounded-full"
src={user.avatar_url}
//width="20rem"
//height="20rem"
alt={`@${user.username}'s avatar`}
/>
)}