Skip to content

Commit

Permalink
Login and logout sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
Ethan-Hill committed Dec 9, 2020
1 parent 756b4b7 commit cb8d760
Show file tree
Hide file tree
Showing 17 changed files with 1,743 additions and 249 deletions.
9 changes: 9 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
"next/babel"
],
"plugins": [
"babel-plugin-macros",
["styled-components", { "ssr": true }]
]
}
14 changes: 14 additions & 0 deletions middlewares/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MongoClient } from "mongodb";

const client = new MongoClient(process.env.DATABASE_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});

export default async function database(req, res, next) {
if (!client.isConnected()) await client.connect();
req.dbClient = client;
req.db = client.db(process.env.DB_NAME);
await setUpDb(req.db);
return next();
}
9 changes: 9 additions & 0 deletions middlewares/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import nextConnect from "next-connect";
import database from "./database";
import session from "./session";

const middleware = nextConnect();

middleware.use(database).use(session);

export default middleware;
15 changes: 15 additions & 0 deletions middlewares/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import session from "express-session";
import connectMongo from "connect-mongo";

const MongoStore = connectMongo(session);

export default function sessionMiddleware(req, res, next) {
const mongoStore = new MongoStore({
client: req.dbClient,
stringify: false,
});
return session({
secret: process.env.SESSION_SECRET,
store: mongoStore,
})(req, res, next);
}
11 changes: 11 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const withCSS = require("@zeit/next-css");
module.exports = withCSS({
webpack: (config, { isServer }) => {
// Fixes npm packages that depend on `fs` module
if (!isServer) {
config.node = { fs: "empty" };
}

return config;
},
});
19 changes: 18 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,25 @@
"start": "next start"
},
"dependencies": {
"@coreui/icons": "^2.0.0-rc.0",
"@zeit/next-css": "^1.0.1",
"connect-mongo": "^3.2.0",
"dotenv": "^8.2.0",
"express-session": "^1.17.1",
"mongodb": "^3.6.3",
"next": "10.0.3",
"next-auth": "^3.1.0",
"next-connect": "^0.9.1",
"next-session": "^3.4.0",
"react": "17.0.1",
"react-dom": "17.0.1"
"react-dom": "17.0.1",
"styled-components": "^5.2.1",
"tailwindcss": "^2.0.1",
"twin.macro": "^2.0.5"
},
"babelMacros": {
"twin": {
"preset": "styled-components"
}
}
}
14 changes: 10 additions & 4 deletions pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import '../styles/globals.css'
import { GlobalStyles } from "twin.macro";
import { Provider } from "next-auth/client";

function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
function App({ Component, pageProps }) {
return (
<Provider session={pageProps.session}>
<GlobalStyles />
<Component {...pageProps} />
</Provider>
);
}

export default MyApp
export default App;
29 changes: 29 additions & 0 deletions pages/_document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Document from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);

return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}
21 changes: 21 additions & 0 deletions pages/api/auth/[...nextauth].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import NextAuth from "next-auth";
import Providers from "next-auth/providers";

const options = {
site: process.env.NEXTAUTH_URL,

// Configure one or more authentication providers
providers: [
Providers.Discord({
clientId: process.env.DISCORD_CLIENT_ID,
clientSecret: process.env.DISCORD_CLIENT_SECRET,
}),
],
database: process.env.DATABASE_URL,
session: {
jwt: true,
maxAge: 30 * 24 * 60 * 60, // 30 days
},
};

export default (req, res) => NextAuth(req, res, options);
16 changes: 16 additions & 0 deletions pages/api/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getSession } from "next-auth/client";

export default async (req, res) => {
const session = await getSession({ req });

if (session) {
res.status(200).json({
message: "You can access this content because you are signed in.",
});
} else {
res.status(403).json({
message:
"You must be sign in to view the protected content on this page.",
});
}
};
6 changes: 0 additions & 6 deletions pages/api/hello.js

This file was deleted.

20 changes: 20 additions & 0 deletions pages/api/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import nextConnect from "next-connect";
import middleware from "../../middlewares/middleware";

const handler = nextConnect();

handler.use(middleware); // see how we're reusing our middleware

// POST /api/users
handler.post(async (req, res) => {
const { name, avatar, email } = req.body;

await req.db
.collection("users")
.insertOne({ name, avatar, email })
.then(() => {
res.status(201);
});
});

export default handler;
127 changes: 66 additions & 61 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,70 @@
import Head from 'next/head'
import styles from '../styles/Home.module.css'

import Head from "next/head";
import { useRouter } from "next/router";
import "twin.macro";
import { signIn, signOut, useSession } from "next-auth/client";
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>

<p className={styles.description}>
Get started by editing{' '}
<code className={styles.code}>pages/index.js</code>
</p>
const [session, loading] = useSession();
const router = useRouter();
if (loading) {
return <p>Loading...</p>;
}

<div className={styles.grid}>
<a href="https://nextjs.org/docs" className={styles.card}>
<h3>Documentation &rarr;</h3>
<p>Find in-depth information about Next.js features and API.</p>
</a>

<a href="https://nextjs.org/learn" className={styles.card}>
<h3>Learn &rarr;</h3>
<p>Learn about Next.js in an interactive course with quizzes!</p>
</a>

<a
href="https://github.com/vercel/next.js/tree/master/examples"
className={styles.card}
>
<h3>Examples &rarr;</h3>
<p>Discover and deploy boilerplate example Next.js projects.</p>
</a>

<a
href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
>
<h3>Deploy &rarr;</h3>
<p>
Instantly deploy your Next.js site to a public URL with Vercel.
</p>
</a>
</div>
</main>
return (
<>
{!session && (
<>
<div>
<Head>
<title>Home</title>
<link rel="icon" href="/favicon.ico" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"
/>
</Head>
<main tw="flex justify-center h-screen w-screen">
<div tw="flex flex-col items-center justify-center w-96 h-96 mt-36">
<h1 tw="text-3xl my-5">Login here 👇</h1>

<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
</a>
</footer>
</div>
)
<button
onClick={signIn}
tw="mt-3 mx-12 text-lg font-semibold
bg-gray-800 w-full text-white rounded-lg
px-6 py-3 block shadow-xl hover:text-white hover:bg-black"
>
<i className="fab fa-discord"></i>
<span tw="ml-2">Login</span>
</button>
</div>
</main>
</div>
</>
)}
{session && (
<>
<Head>
<title>Profile</title>
<link rel="icon" href="/favicon.ico" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"
/>
</Head>
<main tw="flex justify-center h-screen w-screen">
<div tw="flex flex-col items-center justify-center w-96 h-96 mt-36">
<h1 tw="text-3xl my-5">Hey {session.user.name} 👋</h1>
<button
onClick={signOut}
tw="mt-3 mx-12 text-lg font-semibold
bg-gray-800 w-full text-white rounded-lg
px-6 py-3 block shadow-xl hover:text-white hover:bg-black"
>
<span tw="ml-2">Logout</span>
</button>
</div>
</main>
</>
)}
</>
);
}
Loading

0 comments on commit cb8d760

Please sign in to comment.