Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows you to connect and disconnect from oauth providers #155

Merged
merged 1 commit into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bundesliga",
"version": "1.5.0",
"version": "1.5.1",
"private": true,
"scripts": {
"dev": "export NODE_ENV=development; npm install; node scripts/entrypoint.mjs & next dev",
Expand Down
21 changes: 13 additions & 8 deletions pages/api/auth/[...nextauth].js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const options = {
// Goes through every user that has the email or username that was given and has password authentication enabled
const connection = await connect();
const users = await connection.query(
"SELECT * FROM users WHERE (email=? OR username=?) AND password!=''",
[credentials.username, credentials.username]
"SELECT * FROM users WHERE username=? AND password!=''",
[credentials.username]
);
let finished = false;
let result = null;
Expand Down Expand Up @@ -56,12 +56,12 @@ const options = {
credentials.password,
parseInt(process.env.BCRYPT_ROUNDS)
);
connection.query(
"INSERT INTO users (username, password, email) VALUES(?, ?, '')",
await connection.query(
"INSERT INTO users (username, password) VALUES(?, ?)",
[credentials.username, password]
);
const users = await connection.query(
"SELECT * FROM users WHERE (username=? AND password=?) AND email=''",
"SELECT * FROM users WHERE (username=? AND password=?)",
[credentials.username, password]
);
let result = null;
Expand All @@ -82,11 +82,13 @@ const options = {
const connection = await connect();
// Checks if the user has already registered and if no then the user is created
const registered = await connection
.query("SELECT * FROM users WHERE email=?", [profile.email])
.query(`SELECT * FROM users WHERE ${account.provider}=?`, [
profile.email,
])
.then((res) => res.length !== 0);
if (!registered) {
connection.query(
"INSERT INTO users (email, username, password) VALUES (?, ?, '')",
`INSERT INTO users (${account.provider}, username, password) VALUES (?, ?, '')`,
[profile.email, profile.name]
);
}
Expand All @@ -103,7 +105,9 @@ const options = {
if (account.provider === "google" || account.provider === "github") {
const connection = await connect();
token.name = await connection
.query("SELECT id FROM users WHERE email=?", [token.email])
.query(`SELECT id FROM users WHERE ${account.provider}=?`, [
token.email,
])
.then((res) => (res.length > 0 ? res[0].id : 0));
connection.end();
}
Expand All @@ -117,6 +121,7 @@ const options = {
session.user = await connection
.query("SELECT * FROM users WHERE id=?", [session.user.name])
.then((res) => (res.length > 0 ? res[0] : undefined));
session.user.password = session.user.password !== "";
connection.end();
if (session.user !== undefined) {
return session;
Expand Down
25 changes: 25 additions & 0 deletions pages/api/user/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,32 @@ export default async function handler(req, res) {
);
console.log(`User ${id} changed password`);
connection.end();
} else if (
req.body.provider === "google" ||
req.body.provider === "github"
) {
// Used to update the username
const email = String(req.body.email);
const connection = await connect();
// Disconnects the email
if (email == "") {
connection.query(
`UPDATE users SET ${req.body.provider}='' WHERE id=?`,
[id]
);
console.log(`User ${id} disconnected from ${req.body.provider}`);
res.status(200).end(`Disconnected from ${req.body.provider}`);

Check warning

Code scanning / CodeQL

Reflected cross-site scripting

Cross-site scripting vulnerability due to [user-provided value](1).
} else {
connection.query(
`UPDATE users SET ${req.body.provider}=? WHERE id=?`,
[email, id]
);
console.log(`User ${id} connected to ${req.body.provider}`);
res.status(200).end(`Connected to ${req.body.provider}`);

Check warning

Code scanning / CodeQL

Reflected cross-site scripting

Cross-site scripting vulnerability due to [user-provided value](1).
}
connection.end();
} else if (req.body.username === undefined) {
// Used to connect and disconnect from OAuth providers
res.status(500).end("No username given");
} else {
const connection = await connect();
Expand Down
116 changes: 113 additions & 3 deletions pages/usermenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,83 @@ import { useState } from "react";
import Menu from "../components/Menu";
import Head from "next/head";
import { Button, TextField } from "@mui/material";
// Shows the ways to connect and disconnect from a provider
function ProviderShow({ provider, notify, user }) {
const [email, setEmail] = useState(user[provider]);
const [input, setInput] = useState("");
if (email === "") {
return (
<>
<br></br>
<TextField
type="email"
variant="outlined"
size="small"
label="Email"
value={input}
onChange={(e, val) => {
setInput(val);
}}
helperText={`Email used with ${provider}`}
/>
<Button
onClick={() => {
notify(`Connecting to ${provider}`);
fetch(`/api/user`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
provider,
email: input,
}),
}).then(async (response) => {
notify(await response.text(), response.ok ? "success" : "error");
setEmail(input);
});
}}
variant="outlined"
>
Connect to {provider}
</Button>
</>
);
} else {
return (
<>
<br></br>
<Button
variant="outlined"
onClick={() => {
notify(`Disconnecting from ${provider}`);
fetch(`/api/user`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
provider,
email: "",
}),
}).then(async (response) => {
notify(await response.text(), response.ok ? "success" : "error");
setInput("");
setEmail("");
});
}}
>
Disconnect from {provider}
</Button>
</>
);
}
}
// A place to change your username and other settings
export default function Home({ session, user, notify }) {
export default function Home({ session, user, notify, providers }) {
const [username, setUsername] = useState(user.username);
const [password, setPassword] = useState("");
const [passwordExists, setPasswordExists] = useState(user.password);
return (
<>
<Head>
Expand Down Expand Up @@ -49,7 +122,9 @@ export default function Home({ session, user, notify }) {
>
Change Username
</Button>
<br></br>
<p>
Password Auth is currently {passwordExists ? "enabled" : "disabled"}
</p>
<TextField
type="password"
id="password"
Expand All @@ -62,6 +137,7 @@ export default function Home({ session, user, notify }) {
}}
/>
<Button
disabled={password === "" && !passwordExists}
variant="contained"
onClick={() => {
notify("Saving password");
Expand All @@ -76,11 +152,25 @@ export default function Home({ session, user, notify }) {
}),
}).then(async (response) => {
notify(await response.text(), response.ok ? "success" : "error");
setPasswordExists(password !== "");
});
}}
>
{password === "" ? "Disable Password Auth" : "Update Password"}
</Button>
<h2>OAuth Providers</h2>
<p>
Note: If you used an oauth provider before v1.5.1 you will be registered
with both even if you only signed in with one.
</p>
{providers.map((provider) => (
<ProviderShow
key={provider}
provider={provider}
notify={notify}
user={user}
/>
))}
</>
);
}
Expand All @@ -89,7 +179,27 @@ export async function getServerSideProps(ctx) {
const session = await getSession(ctx);
if (session) {
const user = session.user;
return { props: { user } };
// Checks what providers are supported
let providers = [];
if (
!(process.env.GOOGLE_ID === undefined || process.env.GOOGLE_ID === "") &&
!(
process.env.GOOGLE_SECRET === undefined ||
process.env.GOOGLE_SECRET === ""
)
) {
providers.push("google");
}
if (
!(process.env.GITHUB_ID === undefined || process.env.GITHUB_ID === "") &&
!(
process.env.GITHUB_SECRET === undefined ||
process.env.GITHUB_SECRET === ""
)
) {
providers.push("github");
}
return { props: { user, providers } };
} else {
return {
redirect: {
Expand Down
18 changes: 16 additions & 2 deletions scripts/entrypoint.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (process.env.NODE_ENV !== "test") {
dotenv.config({ path: ".env.test.local" });
}
// Used to tell the program what version of the database to use
const currentVersion = "1.5.0";
const currentVersion = "1.5.1";
const date = new Date();
let day = date.getDay();

Expand All @@ -26,7 +26,7 @@ async function startUp() {
await Promise.all([
// Used to store the users
connection.query(
"CREATE TABLE IF NOT EXISTS users (id int PRIMARY KEY AUTO_INCREMENT NOT NULL, email varchar(255), username varchar(255), password varchar(60))"
"CREATE TABLE IF NOT EXISTS users (id int PRIMARY KEY AUTO_INCREMENT NOT NULL, username varchar(255), password varchar(60), google varchar(255) DEFAULT '', github varchar(255) DEFAULT '')"
),
// Used to store the players data
connection.query(
Expand Down Expand Up @@ -190,6 +190,20 @@ async function startUp() {
await connection.query("UPDATE transfers SET max=value");
oldVersion = "1.5.0";
}
if (oldVersion == "1.5.0") {
console.log("Updating database to version 1.5.1");
await connection.query(
"ALTER TABLE users ADD google varchar(255) DEFAULT ''"
);
await connection.query(
"ALTER TABLE users ADD github varchar(255) DEFAULT ''"
);
await connection.query(
"UPDATE users SET google=users.email, github=users.email"
);
await connection.query("ALTER TABLE users DROP COLUMN email");
oldVersion = "1.5.1";
}
// HERE IS WHERE THE CODE GOES TO UPDATE THE DATABASE FROM ONE VERSION TO THE NEXT
// Makes sure that the database is up to date
if (oldVersion !== currentVersion) {
Expand Down