Skip to content

Commit

Permalink
feat: adds authentication using NextAuth
Browse files Browse the repository at this point in the history
  • Loading branch information
ghoshnirmalya committed Aug 27, 2020
1 parent ceb86cf commit 329dc81
Show file tree
Hide file tree
Showing 27 changed files with 2,308 additions and 108 deletions.
4 changes: 4 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
NEXT_PUBLIC_API_URL=http://localhost:1337/graphql
NEXTAUTH_URL=http://localhost:3000
DATABASE_URL=postgres://postgres:@localhost:5432/postgres
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
42 changes: 42 additions & 0 deletions frontend/components/access-denied-indicator/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { FC } from "react";
import { Icon, Flex, Button, Stack, Box } from "@chakra-ui/core";
import Link from "next/link";
import { signIn } from "next-auth/client";

interface IProps {
message?: string;
}

const AccessDeniedIndicator: FC<IProps> = ({
message = "You need to Sign In to view this content!",
}) => {
const iconNode = () => {
return <Icon name="warning-2" color="purple" size="50px" />;
};

const signInButtonNode = () => {
return (
<Link href="/api/auth/signin">
<Button
onClick={(e) => {
e.preventDefault();
signIn();
}}
>
{message}
</Button>
</Link>
);
};

return (
<Flex justifyContent="center" alignItems="center" h="200px">
<Stack spacing={4} align="center">
<Box>{iconNode()}</Box>
<Box>{signInButtonNode()}</Box>
</Stack>
</Flex>
);
};

export default AccessDeniedIndicator;
17 changes: 0 additions & 17 deletions frontend/components/layout/container.js

This file was deleted.

23 changes: 23 additions & 0 deletions frontend/components/layout/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { FC } from "react";
import { Box, useColorMode } from "@chakra-ui/core";

const Container: FC = ({ children }) => {
const { colorMode } = useColorMode();
const bgColor = { light: "gray.100", dark: "gray.900" };
const heightOfNavbar: string = "74px";

return (
<Box
minH={`calc(100vh - ${heightOfNavbar})`}
p={4}
fontSize="sm"
bg={bgColor[colorMode]}
>
<Box maxW="6xl" mx="auto">
{children}
</Box>
</Box>
);
};

export default Container;
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, { FC } from "react";
import { ColorModeProvider, LightMode } from "@chakra-ui/core";
import Container from "components/layout/container";
import React from "react";
import Navbar from "components/navbar";

const Layout = ({ children }) => {
const Layout: FC = ({ children }) => {
return (
<ColorModeProvider>
<LightMode>
<Navbar />
<Container>{children}</Container>
</LightMode>
</ColorModeProvider>
Expand Down
17 changes: 17 additions & 0 deletions frontend/components/loader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { FC } from "react";
import { Box, CircularProgress } from "@chakra-ui/core";

interface Props {
size?: string;
thickness?: number;
}

const Loader: FC<Props> = ({ size = "50px", thickness = 0.15 }) => {
return (
<Box w="full" textAlign="center" maxH="200px">
<CircularProgress isIndeterminate size={size} thickness={thickness} />
</Box>
);
};

export default Loader;
148 changes: 148 additions & 0 deletions frontend/components/navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from "react";
import { NextComponentType } from "next";
import Link from "next/link";
import { signIn, signOut, useSession } from "next-auth/client";
import {
Box,
Stack,
Link as _Link,
Button,
IconButton,
useColorMode,
} from "@chakra-ui/core";

const Navbar: NextComponentType = () => {
const [session] = useSession();
const { colorMode, toggleColorMode } = useColorMode();
const bgColor = { light: "white", dark: "gray.800" };
const color = { light: "gray.800", dark: "gray.100" };

const handleToggleTheme = () => {
console.log("hello");

toggleColorMode();
};

const linksForAllUsers = [
{
id: "home",
label: "Home",
href: "/",
},
];

const linksForAuthenticatedUsers = [
{
id: "feeds",
label: "Feeds",
href: "/feeds",
},
{
id: "myAccount",
label: "My Account",
href: "/my-account",
},
];

const signInButtonNode = () => {
if (session) {
return false;
}

return (
<Box>
<Link href="/api/auth/signin">
<Button
onClick={(e) => {
e.preventDefault();
signIn();
}}
>
Sign In
</Button>
</Link>
</Box>
);
};

const signOutButtonNode = () => {
if (!session) {
return false;
}

return (
<Box>
<Link href="/api/auth/signout">
<Button
onClick={(e) => {
e.preventDefault();
signOut();
}}
>
Sign Out
</Button>
</Link>
</Box>
);
};

const themeToggleButtonNode = () => {
return (
<IconButton
aria-label="Toggle theme"
fontSize="20px"
icon={colorMode === "dark" ? "sun" : "moon"}
onClick={handleToggleTheme}
/>
);
};

return (
<Box bg={bgColor[colorMode]}>
<Box p={4} color={color[colorMode]} shadow="lg" pos="relative">
<Box maxW="6xl" mx="auto" w="full">
<Stack
isInline
spacing={4}
align="center"
justifyContent="space-between"
w="full"
>
<Box>
<Stack isInline spacing={4} align="center" fontWeight="semibold">
{linksForAllUsers.map((link) => {
return (
<Box key={link.id}>
<Link href={link.href}>
<_Link>{link.label}</_Link>
</Link>
</Box>
);
})}
{session &&
linksForAuthenticatedUsers.map((link) => {
return (
<Box key={link.id}>
<Link href={link.href}>
<_Link>{link.label}</_Link>
</Link>
</Box>
);
})}
</Stack>
</Box>
<Box>
<Stack isInline spacing={4} align="center">
{themeToggleButtonNode()}
{signInButtonNode()}
{signOutButtonNode()}
</Stack>
</Box>
</Stack>
</Box>
</Box>
</Box>
);
};

export default Navbar;
48 changes: 48 additions & 0 deletions frontend/components/pages/error/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { FC } from "react";
import { Box, Heading, Stack, Text, Button, Flex } from "@chakra-ui/core";
import Link from "next/link";

interface IProps {
statusCode: number;
}

const IndexPageComponent: FC<IProps> = ({ statusCode }) => {
const heightOfNavbar: string = "74px";
const containerPadding: string = "1rem";

const signOutButtonNode = () => {
return (
<Box>
<Link href="/">
<Button>Return to the home page</Button>
</Link>
</Box>
);
};

return (
<Stack>
<Flex
minH={`calc(100vh - ${heightOfNavbar} - ${containerPadding}*2)`}
justifyContent="center"
alignItems="center"
>
<Stack spacing={4} maxW="xl" mx="auto">
<Heading textAlign="center">Nextjs Strapi Boilerplate</Heading>
<Text fontSize="xl" lineHeight="tall" textAlign="center">
{statusCode
? `An error ${statusCode} occurred on server`
: "An error occurred on client"}
</Text>
<Box>
<Stack isInline align="center" justifyContent="center">
{signOutButtonNode()}
</Stack>
</Box>
</Stack>
</Flex>
</Stack>
);
};

export default IndexPageComponent;
Loading

0 comments on commit 329dc81

Please sign in to comment.