208 lines
7.1 KiB
JavaScript
208 lines
7.1 KiB
JavaScript
import NextAuth from "next-auth";
|
|
import db from "../../../Modules/database";
|
|
import CredentialsProvider from "next-auth/providers/credentials";
|
|
import GoogleProvider from "next-auth/providers/google";
|
|
import GithubProvider from "next-auth/providers/github";
|
|
import { hash, compareSync } from "bcrypt";
|
|
import { sql } from "kysely";
|
|
|
|
let ran = false;
|
|
const options = {
|
|
pages: {
|
|
signIn: "/signin",
|
|
error: "signin",
|
|
},
|
|
// Configure one or more authentication providers
|
|
providers: [
|
|
CredentialsProvider({
|
|
// Used to sign in
|
|
id: "Sign-In",
|
|
name: "Sign-In",
|
|
credentials: {
|
|
username: { label: "Username", type: "username" },
|
|
password: { label: "Password", type: "password" },
|
|
},
|
|
// Used to make sure that the credentails are correct
|
|
authorize: async (credentials) => {
|
|
// Goes through every user that has the email or username that was given and has password authentication enabled
|
|
const users =
|
|
await sql`SELECT * FROM users WHERE username=${credentials.username} AND password!=''`.execute(
|
|
db,
|
|
);
|
|
const unthrottledUsers = users.rows.filter((e) => e.throttle > 0);
|
|
let finished = false;
|
|
let result = null;
|
|
unthrottledUsers.forEach((e) => {
|
|
// Loops through every available user until the password is correct
|
|
console.log("e.password", e.password);
|
|
console.log("credentials.password", credentials.password);
|
|
console.log(
|
|
"compareSync",
|
|
compareSync(credentials.password, e.password),
|
|
);
|
|
console.log("finished", finished);
|
|
if (!finished) {
|
|
// Checks if the password is correct
|
|
if (compareSync(credentials.password, e.password)) {
|
|
finished = true;
|
|
result = { name: e.id };
|
|
} else {
|
|
// Lowers the throttle by 1
|
|
sql`UPDATE users SET throttle=throttle-1 WHERE id=${e.id}`.execute(
|
|
db,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
// Checks if all the users are throttled
|
|
if (unthrottledUsers.length === 0 && users.length > 0) {
|
|
users.rows.forEach((e) => {
|
|
console.log(`User id ${e.id} is locked`);
|
|
});
|
|
return "/error/locked";
|
|
}
|
|
return Promise.resolve(result);
|
|
},
|
|
}),
|
|
CredentialsProvider({
|
|
// Used to sign up
|
|
id: "Sign-Up",
|
|
name: "Sign-Up",
|
|
credentials: {
|
|
username: { label: "Username", type: "username" },
|
|
password: { label: "Password", type: "password" },
|
|
},
|
|
// Used to make sure that the credentails are correct
|
|
authorize: async (credentials) => {
|
|
// Goes through every user that has the email or username that was given
|
|
if (credentials.username == "" || credentials.password == "") {
|
|
throw Error("no_username");
|
|
}
|
|
const bcrypt_rounds =
|
|
parseInt(process.env.BCRYPT_ROUNDS) > 0
|
|
? parseInt(process.env.BCRYPT_ROUNDS)
|
|
: 9;
|
|
const password = await hash(credentials.password, bcrypt_rounds);
|
|
await sql`INSERT INTO users (username, password) VALUES(${credentials.username}, ${password})`.execute(
|
|
db,
|
|
);
|
|
const users =
|
|
await sql`SELECT * FROM users WHERE (username=${credentials.username} AND password=${password})`.execute(
|
|
db,
|
|
);
|
|
|
|
let result = null;
|
|
if (users.rows.length > 0) {
|
|
result = {
|
|
name: users.rows[0].id,
|
|
};
|
|
}
|
|
return Promise.resolve(result);
|
|
},
|
|
}),
|
|
],
|
|
callbacks: {
|
|
async signIn({ account, profile, user }) {
|
|
// Will make sure that if this was sign in with google only a verified user logs in.
|
|
if (account.provider === "google" || account.provider === "github") {
|
|
// Checks if the user has already registered and if no then the user is created
|
|
const registered =
|
|
await sql`SELECT * FROM users WHERE ${sql.raw(account.provider)}=${profile.email}`
|
|
.execute(db)
|
|
.then((e) => e.rows.length > 0);
|
|
if (!registered) {
|
|
await sql`INSERT INTO users (${sql.raw(account.provider)}, username, password) VALUES (${profile.email}, ${profile.name}, '')`.execute(
|
|
db,
|
|
);
|
|
}
|
|
if (account.provider === "google") return profile.email_verified;
|
|
return true;
|
|
}
|
|
await sql`UPDATE users SET admin=1 WHERE id=${process.env.ADMIN}`.execute(
|
|
db,
|
|
);
|
|
await sql`UPDATE users SET admin=0 WHERE id!=${process.env.ADMIN}`.execute(
|
|
db,
|
|
);
|
|
return user;
|
|
},
|
|
async jwt({ token, account }) {
|
|
// Makes sure that the id is in the name parameter
|
|
if (account) {
|
|
// Gets the id from the database
|
|
if (account.provider === "google" || account.provider === "github") {
|
|
token.name =
|
|
await sql`SELECT id FROM users WHERE ${sql.raw(account.provider)}=${token.email}`
|
|
.execute(db)
|
|
.then((res) => (res.rows.length > 0 ? res.rows[0].id : 0));
|
|
}
|
|
}
|
|
return token;
|
|
},
|
|
// Uses the users id and then returns the data for the user
|
|
async session({ session }) {
|
|
if (session && session.user.name) {
|
|
await sql`UPDATE users SET active=1 WHERE id=${session.user.name} AND active=0`.execute(
|
|
db,
|
|
);
|
|
session.user =
|
|
await sql`SELECT * FROM users WHERE id=${session.user.name}`
|
|
.execute(db)
|
|
.then((res) => (res.rows.length > 0 ? res.rows[0] : undefined));
|
|
if (session.user !== undefined) {
|
|
session.user.password = session.user.password !== "";
|
|
session.user.active = session.user.active == 1;
|
|
session.user.admin = session.user.admin == 1;
|
|
return session;
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
},
|
|
};
|
|
|
|
export default async function authenticate(req, res) {
|
|
if (ran === false) {
|
|
// Only adds sign in with github and google if they are setup by the server owner
|
|
if (
|
|
!(process.env.GITHUB_ID === undefined || process.env.GITHUB_ID === "") &&
|
|
!(
|
|
process.env.GITHUB_SECRET === undefined ||
|
|
process.env.GITHUB_SECRET === ""
|
|
)
|
|
) {
|
|
options.providers = [
|
|
GithubProvider({
|
|
clientId: process.env.GITHUB_ID,
|
|
clientSecret: process.env.GITHUB_SECRET,
|
|
}),
|
|
...options.providers,
|
|
];
|
|
}
|
|
if (
|
|
!(process.env.GOOGLE_ID === undefined || process.env.GOOGLE_ID === "") &&
|
|
!(
|
|
process.env.GOOGLE_SECRET === undefined ||
|
|
process.env.GOOGLE_SECRET === ""
|
|
)
|
|
) {
|
|
options.providers = [
|
|
GoogleProvider({
|
|
clientId: process.env.GOOGLE_ID,
|
|
clientSecret: process.env.GOOGLE_SECRET,
|
|
authorization: {
|
|
params: {
|
|
prompt: "consent",
|
|
access_type: "offline",
|
|
response_type: "code",
|
|
},
|
|
},
|
|
}),
|
|
...options.providers,
|
|
];
|
|
}
|
|
ran = true;
|
|
}
|
|
await NextAuth(req, res, options);
|
|
}
|
|
export const authOptions = options;
|