mirror of
https://github.com/Alee14/bnbso-auth.git
synced 2025-01-22 10:41:57 -05:00
Ability to change password; Sim time on dashboard
This commit is contained in:
parent
39cbc8c286
commit
b2748a5c55
12 changed files with 160 additions and 58 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -174,4 +174,6 @@ dist
|
|||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
|
||||
*.db
|
||||
*.db
|
||||
|
||||
.idea/
|
|
@ -1,5 +1,5 @@
|
|||
# bnbso-auth
|
||||
Web authentication for bnbSO (registering accounts, resetting passwords, changing passwords) using Discord authentication. Designed for FreeSO-based servers.
|
||||
Web authentication for bnbSO (registering accounts, changing passwords) using Discord authentication. Designed for FreeSO-based servers.
|
||||
|
||||
To install dependencies:
|
||||
|
||||
|
@ -10,7 +10,7 @@ bun install
|
|||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
bun run index.js
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.1.38. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||
|
|
63
index.js
63
index.js
|
@ -86,7 +86,7 @@ app.get("/", async (req, res) => {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
return res.render('error', { error: 'You must be a member of the bits & Bytes server to access this page.' });
|
||||
return res.render('error', { error: 'You must be a member of that server to access this page.' });
|
||||
}
|
||||
} else {
|
||||
res.render('index');
|
||||
|
@ -105,7 +105,7 @@ app.post("/register", upload.none(), async (req, res) => {
|
|||
try {
|
||||
const form = new FormData();
|
||||
form.append('username', username);
|
||||
form.append('email', id + '@discord.com');
|
||||
form.append('email', `${id}@discord.com`);
|
||||
form.append('password', password);
|
||||
form.append('key', process.env.REG_KEY);
|
||||
|
||||
|
@ -123,7 +123,7 @@ app.post("/register", upload.none(), async (req, res) => {
|
|||
console.error("Error inserting user data into database:", err);
|
||||
return res.render('register', { ...req.user, error: "An error occurred during registration, contact server operator." });
|
||||
}
|
||||
return res.render('success');
|
||||
return res.render('success', { ...req.user, success: "Created account successfully!"});
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -131,7 +131,62 @@ app.post("/register", upload.none(), async (req, res) => {
|
|||
return res.render('register', { ...req.user, error: "An error occurred during registration, contact server operator." });
|
||||
}
|
||||
} else {
|
||||
res.redirect("/");
|
||||
res.status(401).send("Unauthorized.");
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/password', (req, res) => {
|
||||
if (req.isAuthenticated()) {
|
||||
res.render('password');
|
||||
} else {
|
||||
res.redirect("/auth/discord");
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/password/change', upload.none(), async (req, res) => {
|
||||
if (req.isAuthenticated()) {
|
||||
const { id } = req.user;
|
||||
const { currentpassword, newpassword, newpassword2 } = req.body;
|
||||
|
||||
if (newpassword !== newpassword2) {
|
||||
return res.render('password', { ...req.user, error: "Passwords do not match" });
|
||||
}
|
||||
|
||||
try {
|
||||
db.get(`SELECT * FROM users WHERE discord_id = ?`, [id], async (err, row) => {
|
||||
if (err) {
|
||||
console.error("Error querying the database:", err);
|
||||
return res.render('password', {...req.user, error: "An error occurred while checking user data."});
|
||||
}
|
||||
|
||||
if (row) {
|
||||
const form = new FormData();
|
||||
form.append('username', row.fso_username);
|
||||
form.append('old_password', currentpassword);
|
||||
form.append('new_password', newpassword);
|
||||
|
||||
const response = await axios.post(`${process.env.API_URL}/userapi/password`, form, {
|
||||
headers: form.getHeaders()
|
||||
});
|
||||
|
||||
if (response.data.error) {
|
||||
const errorKey = response.data.error_description || "default";
|
||||
const errorMessage = statusMessages.password_reset_errors[errorKey] || "Something went wrong";
|
||||
|
||||
return res.render('password', { ...req.user, error: errorMessage });
|
||||
}
|
||||
|
||||
return res.render('success', { ...req.user, success: "Password changed successfully!" });
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error during password change:", error);
|
||||
return res.render('password', { ...req.user, error: "An error occurred during password change, contact server operator." });
|
||||
}
|
||||
|
||||
} else {
|
||||
res.status(401).send("Unauthorized.");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
{
|
||||
"name": "bnbso-auth",
|
||||
"module": "index.ts",
|
||||
"module": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
|
@ -20,4 +23,4 @@
|
|||
"passport-discord": "^0.1.4",
|
||||
"sqlite3": "^5.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');
|
||||
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
|
@ -34,7 +34,7 @@ a:active {
|
|||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
background-color: #00633a;
|
||||
background-color: #535353;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
transition: 0.2s;
|
||||
|
@ -43,12 +43,12 @@ a:active {
|
|||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #009959;
|
||||
background-color: #8a8a8a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.button:active {
|
||||
background-color: #003620;
|
||||
background-color: #454545;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
@ -139,4 +139,9 @@ button {
|
|||
.error {
|
||||
color: #f88c8c;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.success {
|
||||
color: #a3f88c;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
|
37
status.json
37
status.json
|
@ -1,29 +1,28 @@
|
|||
{
|
||||
"registration_errors": {
|
||||
"missing_confirmation_token": "Registration failed: Missing confirmation token.",
|
||||
"user_short": "Registration failed: Username is too short.",
|
||||
"user_long": "Registration failed: Username is too long.",
|
||||
"user_invalid": "Registration failed: Invalid username.",
|
||||
"pass_required": "Registration failed: Password is required.",
|
||||
"email_invalid": "Registration failed: Invalid email address.",
|
||||
"ip_banned": "Registration failed: IP is banned.",
|
||||
"registrations_too_frequent": "Registration failed: Too many registrations from this IP address.",
|
||||
"user_exists": "Registration failed: User already exists.",
|
||||
"smtp_disabled": "Registration failed: SMTP service is disabled.",
|
||||
"email_taken": "Registration failed: Email address is already taken.",
|
||||
"confirmation_pending": "Registration failed: Confirmation pending.",
|
||||
"key_wrong": "Registration failed: Invalid registration key."
|
||||
"missing_confirmation_token": "Missing confirmation token.",
|
||||
"user_short": "Username is too short.",
|
||||
"user_long": "Username is too long.",
|
||||
"user_invalid": "Invalid username.",
|
||||
"pass_required": "Password is required.",
|
||||
"email_invalid": "Invalid email address.",
|
||||
"ip_banned": "IP is banned.",
|
||||
"registrations_too_frequent": "Too many registrations from this IP address.",
|
||||
"user_exists": "User already exists.",
|
||||
"smtp_disabled": "SMTP service is disabled.",
|
||||
"email_taken": "Email address is already taken.",
|
||||
"confirmation_pending": "Confirmation pending.",
|
||||
"key_wrong": "Invalid registration key."
|
||||
},
|
||||
"password_reset_errors": {
|
||||
"missing_fields": "Password reset failed: Missing required fields.",
|
||||
"email_invalid": "Password reset failed: Invalid email address.",
|
||||
"user_invalid": "Password reset failed: User does not exist.",
|
||||
"incorrect_password": "Password reset failed: Incorrect password.",
|
||||
"invalid_token": "Password reset failed: Invalid confirmation token."
|
||||
"missing_fields": "Missing required fields.",
|
||||
"email_invalid": "Invalid email address.",
|
||||
"user_invalid": "User does not exist.",
|
||||
"incorrect_password": "Incorrect password.",
|
||||
"invalid_token": "Invalid confirmation token."
|
||||
},
|
||||
"success_responses": {
|
||||
"success": "Operation was successful.",
|
||||
"email_failed": "Email sending failed."
|
||||
}
|
||||
}
|
||||
|
|
@ -9,12 +9,44 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<h1>Welcome, <%= username %>!</h1>
|
||||
<h2>FreeSO Username: <%= fso_username %></h2>
|
||||
<a href="#" class="button">Change Password</a>
|
||||
<a href="#" class="button">Download bnbSO Client</a>
|
||||
<h2>bnbSO Username: <%= fso_username %></h2>
|
||||
<h2 id="simtime"></h2>
|
||||
<a href="/password" class="button">Change Password</a>
|
||||
<a href="https://fso-builds.riperiperi.workers.dev" class="button">Download bnbSO Client</a>
|
||||
<a href="/logout" class="button logout">Logout</a>
|
||||
</div>
|
||||
<script>
|
||||
function updateTSOClock() {
|
||||
const currentTime = new Date(),
|
||||
utcMinutes = currentTime.getUTCMinutes(),
|
||||
utcSeconds = currentTime.getUTCSeconds();
|
||||
let timePeriod = 'AM', totalSeconds = 0;
|
||||
if (currentTime.getUTCHours() % 2 === 1) {
|
||||
totalSeconds = 3600;
|
||||
timePeriod = 'PM';
|
||||
}
|
||||
totalSeconds += utcMinutes * 60 + utcSeconds;
|
||||
let hour = Math.floor(totalSeconds / 300);
|
||||
if (hour > 12) {
|
||||
hour -= 12;
|
||||
}
|
||||
if (hour === 0) {
|
||||
hour = 12;
|
||||
}
|
||||
let minute = Math.floor(totalSeconds % 300 / 5);
|
||||
if (minute < 10) {
|
||||
minute = '0' + minute;
|
||||
}
|
||||
const simTimeElement = document.querySelector('#simtime');
|
||||
if (simTimeElement) {
|
||||
simTimeElement.textContent = `${hour}:${minute} ${timePeriod}`;
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(updateTSOClock, 1000);
|
||||
updateTSOClock();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<h1>Oh no! Something went wrong!</h1>
|
||||
<p><%= error %></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<p>Log into your Discord account to get access to bnbSO.</p>
|
||||
<p><i>You must be a bits & Bytes member.</i></p>
|
||||
<a class="button discord" href="/auth/discord">Login with Discord</a>
|
||||
<a class="button discord" href="/auth/discord">Login with Discord</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -9,18 +9,22 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<h1>Change Password</h1>
|
||||
<p>If you have issues changing your password, ask the server operator to change your password.</p>
|
||||
<form method="post" action="/login">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username">
|
||||
<label for="password">Current Password:</label>
|
||||
<input type="password" id="password" name="password">
|
||||
<button type="submit">Login</button>
|
||||
<p>If you have issues changing your password, ask the server operator to reset your password.</p>
|
||||
<form method="post" action="/password/change">
|
||||
<label for="currentpassword">Current Password:</label>
|
||||
<input type="password" id="currentpassword" name="currentpassword">
|
||||
<label for="newpassword">New Password:</label>
|
||||
<input type="password" id="newpassword" name="newpassword">
|
||||
<label for="newpassword2">Confirm New Password:</label>
|
||||
<input type="password" id="newpassword2" name="newpassword2">
|
||||
<button type="submit">Change Password</button>
|
||||
</form>
|
||||
<a href="/" class="button">Dashboard</a>
|
||||
<% if (typeof error !== 'undefined') { %>
|
||||
<div class="error"><%= error %></div>
|
||||
<% } %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<h1>Welcome to bnbSO!</h1>
|
||||
<p>You will be sending the following information to register your bnbSO account</p>
|
||||
<p>Please verify that the following information is correct. You can only change your username <b>once</b>.</p>
|
||||
|
@ -25,5 +25,6 @@
|
|||
<% if (typeof error !== 'undefined') { %>
|
||||
<div class="error"><%= error %></div>
|
||||
<% } %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
<body>
|
||||
<div class="background"></div>
|
||||
<div class="container">
|
||||
<img src="img/logo.png" alt="logo" width="200">
|
||||
<p>Created account successfully!</p>
|
||||
<img src="/img/logo.png" alt="logo" width="200">
|
||||
<h1>Success!</h1>
|
||||
<p class="success"><%= success %></p>
|
||||
<a href="/">Dashboard</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue