discord authentication
This commit is contained in:
parent
0a26a8b4a8
commit
3bbfed025d
@ -18,19 +18,27 @@
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"canvas": "^3.1.0",
|
||||
"connect-flash": "^0.1.1",
|
||||
"discord.js": "^14.17.3",
|
||||
"dotenv": "^16.4.7",
|
||||
"ejs": "^3.1.10",
|
||||
"ejs-mate": "^4.0.0",
|
||||
"express": "^4.21.2",
|
||||
"express-session": "^1.18.1",
|
||||
"ncp": "^2.0.0",
|
||||
"passport": "^0.7.0",
|
||||
"passport-discord": "^0.1.4",
|
||||
"preline": "^2.7.0",
|
||||
"tsconfig-paths": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/connect-flash": "^0.0.40",
|
||||
"@types/ejs": "^3.1.5",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/express-session": "^1.18.1",
|
||||
"@types/node": "^22.10.10",
|
||||
"@types/passport": "^1.0.17",
|
||||
"@types/passport-discord": "^0.1.14",
|
||||
"@zerollup/ts-transform-paths": "^1.7.18",
|
||||
"nodemon": "^3.1.9",
|
||||
"tailwindcss": "^3.4.17",
|
||||
|
28
src/app.ts
28
src/app.ts
@ -1,15 +1,22 @@
|
||||
import express from "express";
|
||||
import engine from "ejs-mate";
|
||||
import passport from "passport";
|
||||
import session from "express-session";
|
||||
import flash from "connect-flash";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
import "@bot/bot";
|
||||
import { setupPassport } from "@server/controllers/auth";
|
||||
import { attachUser } from "@server/middleware/attachUser";
|
||||
import { flashMiddleware } from "@server/middleware/flash";
|
||||
import { ensureAuthenticated } from "@server/middleware/authenticated";
|
||||
|
||||
// import routers & middleware
|
||||
import { attachGuilds } from "@server/middleware/attachGuilds";
|
||||
import { router as homeRouter } from "@server/routes/home";
|
||||
import { router as guildRouter } from "@server/routes/guild";
|
||||
import { router as loginRouter } from "@server/routes/login";
|
||||
import { router as authRouter } from "@server/routes/auth";
|
||||
|
||||
const app = express();
|
||||
|
||||
@ -20,10 +27,23 @@ app.set("view engine", "ejs");
|
||||
app.use("/static", express.static("./src/client/public"));
|
||||
app.use("/static/preline.js", express.static("./node_modules/preline/dist/preline.js"));
|
||||
|
||||
app.use(session({
|
||||
secret: "unsecure-development-secret",
|
||||
resave: true,
|
||||
saveUninitialized: true
|
||||
}));
|
||||
|
||||
setupPassport(passport);
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
app.use(flash());
|
||||
app.use(flashMiddleware);
|
||||
|
||||
// register routers & middleware
|
||||
app.use("/", attachGuilds, homeRouter);
|
||||
app.use("/guild", attachGuilds, guildRouter);
|
||||
app.use("/login", loginRouter);
|
||||
app.use("/login", authRouter);
|
||||
app.use("/guild", ensureAuthenticated, attachUser, attachGuilds, guildRouter);
|
||||
app.use("/", ensureAuthenticated, attachUser, attachGuilds, homeRouter);
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
|
@ -58,7 +58,7 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
dark:border-neutral-700;
|
||||
}
|
||||
|
||||
.sidebar-aside.sidebar-main {
|
||||
.sidebar-aside.main-sidebar {
|
||||
@apply
|
||||
[--auto-close:lg]
|
||||
lg:block
|
||||
@ -84,7 +84,8 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
duration-200
|
||||
lg:duration-100
|
||||
ease-in
|
||||
start-64
|
||||
start-0
|
||||
lg:start-64
|
||||
z-[59]
|
||||
}
|
||||
|
||||
|
@ -878,6 +878,11 @@ video {
|
||||
height: 46px;
|
||||
}
|
||||
|
||||
.size-\[50px\] {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.\!h-2\.5 {
|
||||
height: 0.625rem !important;
|
||||
}
|
||||
@ -898,6 +903,10 @@ video {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.h-screen {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.max-h-full {
|
||||
max-height: 100%;
|
||||
}
|
||||
@ -926,6 +935,10 @@ video {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
.w-\[26rem\] {
|
||||
width: 26rem;
|
||||
}
|
||||
|
||||
.w-\[calc\(100\%-2rem\)\] {
|
||||
width: calc(100% - 2rem);
|
||||
}
|
||||
@ -1292,11 +1305,6 @@ video {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.px-2\.5 {
|
||||
padding-left: 0.625rem;
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
@ -1704,7 +1712,7 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
background-color: rgb(38 38 38 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.sidebar-aside.sidebar-main {
|
||||
.sidebar-aside.main-sidebar {
|
||||
inset-inline-start: 0px;
|
||||
z-index: 60;
|
||||
--tw-translate-x: -100%;
|
||||
@ -1717,7 +1725,7 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.sidebar-aside.sidebar-main {
|
||||
.sidebar-aside.main-sidebar {
|
||||
inset-inline-end: auto;
|
||||
bottom: 0px;
|
||||
display: block;
|
||||
@ -1727,7 +1735,7 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
}
|
||||
|
||||
.sidebar-aside.guild-sidebar {
|
||||
inset-inline-start: 16rem;
|
||||
inset-inline-start: 0px;
|
||||
z-index: 59;
|
||||
--tw-translate-x: -100%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
@ -1742,6 +1750,7 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
.sidebar-aside.guild-sidebar {
|
||||
inset-inline-end: auto;
|
||||
bottom: 0px;
|
||||
inset-inline-start: 16rem;
|
||||
display: block;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
|
@ -1,17 +1,22 @@
|
||||
<nav class="bg-white dark:bg-neutral-900">
|
||||
<div class="max-w-[85rem] w-full mx-auto sm:flex sm:flex-row sm:justify-between sm:items-center sm:gap-x-3 py-3 px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center gap-x-3">
|
||||
<div class="grow flex gap-x-4">
|
||||
<div class="grow flex items-center gap-x-4">
|
||||
<% if (guild.icon) { %>
|
||||
<img class="size-[28px] rounded" src="<%= guild.iconURL() %>" alt="<%= guild.name %>">
|
||||
<img class="size-[50px] rounded" src="<%= guild.iconURL() %>" alt="<%= guild.name %>">
|
||||
<% } else { %>
|
||||
<div class="size-[28px] flex shrink-0 justify-center items-center rounded bg-neutral-100 dark:bg-neutral-800">
|
||||
<div class="size-[50px] flex shrink-0 justify-center items-center rounded bg-neutral-100 dark:bg-neutral-800">
|
||||
<span class="text-xs"><%= guild.name.split(" ").slice(0, 2).map(word => word[0].toUpperCase()).join(""); %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
<span class="font-semibold whitespace-nowrap text-gray-800 dark:text-neutral-200">
|
||||
<%= guild.name %>
|
||||
</span>
|
||||
<div class="d-flex items-center">
|
||||
<span class="font-semibold whitespace-nowrap text-2xl text-gray-800 dark:text-neutral-200">
|
||||
<%= guild.name %>
|
||||
</span>
|
||||
<span class="font-mono whitespace-nowrap text-sm text-gray-500 dark:text-neutral-500">
|
||||
<%= guild.id %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="hs-collapse-toggle capitalize sm:hidden py-1.5 px-2 inline-flex items-center font-medium text-xs rounded-md border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 focus:outline-none focus:bg-gray-100 dark:border-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700" data-hs-collapse="#guildScreenDropdown">
|
||||
|
@ -7,7 +7,7 @@
|
||||
<!-- Grid -->
|
||||
<div class="grid sm:grid-cols-2 xl:grid-cols-4 gap-4 sm:gap-6">
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-md dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="p-4 md:p-5 flex gap-x-4">
|
||||
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
|
||||
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||||
@ -43,7 +43,7 @@
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-md dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="p-4 md:p-5 flex gap-x-4">
|
||||
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
|
||||
<svg class="shrink-0 size-6 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="9" x2="20" y2="9"></line><line x1="4" y1="15" x2="20" y2="15"></line><line x1="10" y1="3" x2="8" y2="21"></line><line x1="16" y1="3" x2="14" y2="21"></line></svg>
|
||||
@ -66,7 +66,7 @@
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-md dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="p-4 md:p-5 flex gap-x-4">
|
||||
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
|
||||
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>
|
||||
@ -95,7 +95,7 @@
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex flex-col bg-white border shadow-sm rounded-md dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="p-4 md:p-5 flex gap-x-4">
|
||||
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
|
||||
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg>
|
||||
|
@ -6,30 +6,55 @@
|
||||
<title><%= title %></title>
|
||||
<link rel="stylesheet" href="/static/css/tailwind.css">
|
||||
</head>
|
||||
<body class="bg-neutral-100 dark:bg-neutral-900 text-gray-600 dark:text-gray-400 font-[Inter]">
|
||||
<div class="container mx-auto text-center mt-64">
|
||||
<body class="h-screen flex justify-center items-center bg-neutral-100 dark:bg-neutral-900 text-gray-600 dark:text-gray-400 font-[Inter]">
|
||||
<div class="mt-7 w-[26rem] bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-neutral-900 dark:border-neutral-700">
|
||||
<div class="p-4 sm:p-7">
|
||||
<div class="text-center">
|
||||
<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Sign in</h1>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-neutral-400">
|
||||
Login is required to use Relay.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<a href="/login/api" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-800 dark:focus:bg-neutral-800">
|
||||
<svg class="w-4 h-auto" xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
|
||||
<path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059l-.018-.011a9 9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066l.015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/>
|
||||
</svg>
|
||||
Sign in with Discord
|
||||
</a>
|
||||
</div>
|
||||
<% if (error != "") { %>
|
||||
<%= error %>
|
||||
<% } if (success != "") { %>
|
||||
<%= success %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="container mx-auto text-center mt-64">
|
||||
<div class="max-w-md mx-auto p-4 sm:p-6 space-y-4 sm:space-y-6">
|
||||
<div class="mt-7 bg-white border border-gray-200 rounded-xl shadow-sm dark:bg-neutral-900 dark:border-neutral-700">
|
||||
<div class="p-4 sm:p-7">
|
||||
<div class="text-center">
|
||||
<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Sign in</h1>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-neutral-400">
|
||||
Login is required to use Relay.
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="block text-2xl font-bold text-gray-800 dark:text-white">Sign in</h1>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-neutral-400">
|
||||
Login is required to use Relay.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<button type="button" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-800 dark:focus:bg-neutral-800">
|
||||
<svg class="w-4 h-auto" xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
|
||||
<path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059l-.018-.011a9 9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066l.015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/>
|
||||
</svg>
|
||||
Sign in with Discord
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button type="button" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-800 dark:focus:bg-neutral-800">
|
||||
<svg class="w-4 h-auto" xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
|
||||
<path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059l-.018-.011a9 9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066l.015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/>
|
||||
</svg>
|
||||
Sign in with Discord
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<script src="/static/preline.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -10,7 +10,7 @@
|
||||
<!-- End Mobile Sidebar Controls -->
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside id="layoutSidebarMain" class="sidebar-aside sidebar-main hs-overlay hs-overlay-open:translate-x-0" role="dialog" tabindex="-1">
|
||||
<aside id="layoutSidebarMain" class="sidebar-aside main-sidebar hs-overlay hs-overlay-open:translate-x-0" role="dialog" tabindex="-1">
|
||||
<div class="sidebar-container">
|
||||
<!-- Sidebar Header -->
|
||||
<div class="sidebar-header">
|
||||
@ -67,8 +67,8 @@
|
||||
<div class="mt-auto p-2 border-t border-gray-200 dark:border-neutral-700">
|
||||
<div class="hs-dropdown [--strategy:absolute] [--auto-close:inside] relative w-full inline-flex">
|
||||
<button type="button" id="userMenu" class="w-full inline-flex shrink-0 items-center gap-x-2 p-2 text-start text-sm text-gray-800 rounded-md hover:bg-gray-100 focus:outline-none focus:bg-gray-100 dark:text-neutral-200 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700">
|
||||
<img class="shrink-0 size-5 rounded-full" src="https://images.unsplash.com/photo-1734122415415-88cb1d7d5dc0?q=80&w=320&h=320&auto=format&fit=facearea&facepad=3&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Avatar">
|
||||
Username Here
|
||||
<img class="shrink-0 size-5 rounded-full" src="https://cdn.discordapp.com/avatars/<%= user.id %>/<%= user.avatar %>" alt="Avatar">
|
||||
<%= user.username %>
|
||||
<svg class="block hs-dropdown-open:hidden ms-auto size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>
|
||||
<svg class="hidden hs-dropdown-open:block ms-auto size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
|
||||
</button>
|
||||
|
45
src/server/controllers/auth.ts
Normal file
45
src/server/controllers/auth.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import passport, { PassportStatic } from "passport"
|
||||
import { Strategy, Profile } from "passport-discord";
|
||||
|
||||
export const get = async (_request: Request, response: Response) => {
|
||||
response.render("login", {
|
||||
title: "Login - Relay"
|
||||
});
|
||||
};
|
||||
|
||||
export const authenticate = async (request: Request, response: Response, next: NextFunction) => {
|
||||
passport.authenticate("discord", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/login",
|
||||
failureFlash: true
|
||||
})(request, response, next);
|
||||
};
|
||||
|
||||
export const setupPassport = (passport: PassportStatic) => {
|
||||
const scopes: Array<string> = ["identify"];
|
||||
const authorisedUserIds: Array<string> = process.env.DISCORD_USER_IDS?.split("/") || [];
|
||||
passport.use(new Strategy({
|
||||
clientID: process.env.CLIENT_ID || "",
|
||||
clientSecret: process.env.CLIENT_SECRET || "",
|
||||
callbackURL: process.env.CALLBACK_URL || "",
|
||||
scope: scopes
|
||||
},
|
||||
(_accessToken: string, _refreshToken: string, profile: Profile, callback: CallableFunction) => {
|
||||
if (authorisedUserIds.includes(profile.id)) {
|
||||
return callback(null, profile);
|
||||
}
|
||||
|
||||
return callback(null, false, {
|
||||
"message": "User ID is not authorised!"
|
||||
})
|
||||
}));
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user);
|
||||
});
|
||||
|
||||
passport.deserializeUser((user: any, done) => {
|
||||
done(null, user);
|
||||
});
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { Request, Response } from "express";
|
||||
|
||||
export const get = async (_request: Request, response: Response) => {
|
||||
response.render("login", {
|
||||
title: "Login - Relay"
|
||||
});
|
||||
};
|
6
src/server/middleware/attachUser.ts
Normal file
6
src/server/middleware/attachUser.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
|
||||
export const attachUser = (request: Request, response: Response, next: NextFunction) => {
|
||||
response.locals.user = request.user;
|
||||
next();
|
||||
};
|
@ -1,9 +1,17 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
|
||||
// export const ensureAuthenticated = (request: Request, response: Response, next: NextFunction) => {
|
||||
// if (request.isAuthenticated()) {
|
||||
// return next();
|
||||
// }
|
||||
export const ensureAuthenticated = (request: Request, response: Response, next: NextFunction) => {
|
||||
if (request.isAuthenticated()) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// response.redirect("/login");
|
||||
// };
|
||||
response.redirect("/login");
|
||||
};
|
||||
|
||||
export const forwardAuthenticated = (request: Request, response: Response, next: NextFunction) => {
|
||||
if (request.isAuthenticated()) {
|
||||
return response.redirect("/");
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
7
src/server/middleware/flash.ts
Normal file
7
src/server/middleware/flash.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
|
||||
export const flashMiddleware = (request: Request, response: Response, next: NextFunction) => {
|
||||
response.locals.success = request.flash("success");
|
||||
response.locals.error = request.flash("error");
|
||||
next();
|
||||
};
|
8
src/server/routes/auth.ts
Normal file
8
src/server/routes/auth.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Router } from "express";
|
||||
import { forwardAuthenticated } from "@server/middleware/authenticated";
|
||||
import * as controller from "@server/controllers/auth";
|
||||
|
||||
export const router = Router();
|
||||
|
||||
router.get("/", forwardAuthenticated, controller.get);
|
||||
router.get("/api", forwardAuthenticated, controller.authenticate);
|
@ -1,6 +0,0 @@
|
||||
import { Router } from "express";
|
||||
import * as controller from "@server/controllers/login";
|
||||
|
||||
export const router = Router();
|
||||
|
||||
router.get("/", controller.get);
|
Loading…
x
Reference in New Issue
Block a user