Basic Cleanup (#1)

Reviewed-on: #1
Co-authored-by: Armored-Dragon <forgejo3829105@armoreddragon.com>
Co-committed-by: Armored-Dragon <forgejo3829105@armoreddragon.com>
pull/2/head
Armored Dragon 2023-10-27 22:26:28 +00:00 committed by Armored Dragon
parent 66c463f80a
commit f5cab625ec
8 changed files with 84 additions and 51 deletions

View File

@ -14,9 +14,10 @@ const s3 = new S3Client({
});
const settings = require("../settings");
// FIXME: This does not properly validate that a user was created
async function registerUser(username, password, options) {
const new_user = await prisma.user.create({ data: { username: username, password: password, ...options } });
await settings.setSetupComplete();
settings.act("SETUP_COMPLETE", true);
if (new_user) return { success: true, message: `Successfully created ${new_user.username}` };
}

View File

@ -1,6 +1,3 @@
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
const core = require("./core");
const settings = require("../settings");
async function userRegistration(username, password) {
@ -9,20 +6,16 @@ async function userRegistration(username, password) {
// TODO: Admin customizable minimum password length
if (password.length < 4) return { success: false, message: "Password not long enough" };
const existing_user = await core.getUser({ username: username });
if (existing_user.success) return { success: false, message: "Username already exists" };
// Check if username only uses URL safe characters
if (!is_url_safe(username)) return { success: false, message: "Username is not URL safe" };
// All good! Validation complete
return { success: true };
}
async function userLogin(username, password) {
const existing_user = await core.getUser({ username: username });
if (!existing_user.success) return { success: false, message: "User does not exist" };
if (existing_user.role === "LOCKED") return { success: false, message: "Account is locked: Contact your administrator" };
return { success: true, data: existing_user.data };
function is_url_safe(str) {
const pattern = /^[A-Za-z0-9\-_.~]+$/;
return pattern.test(str);
}
module.exports = { userRegistration, userLogin };
module.exports = { userRegistration };

View File

@ -3,35 +3,37 @@ const core = require("./core");
const settings = require("../settings");
async function registerUser(username, password) {
const registration_allowed = await settings.userRegistrationAllowed(); // Check if user registration is allowed
// Get current and relevant settings
const s = Promise.all([settings.act("ACCOUNT_REGISTRATION"), settings.act("SETUP_COMPLETE")]);
const form_valid = await validate.userRegistration(username, password); // Check form for errors
const is_setup_complete = await settings.setupComplete();
let role = is_setup_complete ? undefined : "ADMIN";
// Set variables for easy reading
const registration_allowed = s[0];
const setup_complete = s[1];
if (!registration_allowed && setup_complete) return { success: false, message: "Registration is disabled" }; // Registration disabled
if (!form_valid.success) return form_valid; // Registration details did not validate
// Does a user using that username exist already?
const existing_user = await core.getUser({ username: username });
if (existing_user.success) return { success: false, message: "Username is taken" };
// Register the user in the database
if (registration_allowed && form_valid.success) return await core.registerUser(username, password, { role: role });
const role = setup_complete ? undefined : "ADMIN";
const registration_status = await core.registerUser(username, password, { role: role });
// Something went wrong!
return { success: false, message: form_valid.message };
if (registration_status.success) return registration_status;
else return registration_status;
}
async function loginUser(username, password) {
const user = await validate.userLogin(username);
if (!user.success) return user;
// Get the user by username
const existing_user = await core.getUser({ username: username });
return { success: true, data: { username: user.data.username, id: user.data.id, password: user.data.password } };
// Check for errors or problems
if (!existing_user.success) return { success: false, message: "User does not exist" };
if (existing_user.role === "LOCKED") return { success: false, message: "Account is locked: Contact your administrator" };
return { success: true, data: { username: existing_user.data.username, id: existing_user.data.id, password: existing_user.data.password } };
}
async function getUser({ id, username } = {}) {
let user;
if (id) user = await core.getUser({ id: id });
else if (username) user = await core.getUser({ username: username });
// Make sure we only get important identifier and nothing sensitive!
if (user.success) return { success: true, data: { username: user.data.username, id: user.data.id, role: user.data.role } };
return { success: false, message: "No user found" };
}
module.exports = { registerUser, loginUser, getUser };
module.exports = { registerUser, loginUser };

View File

@ -4,7 +4,7 @@ const settings = require("./settings");
async function index(request, response) {
// Check if the master admin has been created
const is_setup_complete = (await settings.setupComplete()) || false;
const is_setup_complete = (await settings.act("SETUP_COMPLETE")) || false;
if (!is_setup_complete) return response.redirect("/register");
response.render("index.ejs", { user: request.session.user || null, website_name: process.env.WEBSITE_NAME });
@ -36,8 +36,10 @@ async function registerPost(request, response) {
async function loginPost(request, response) {
const login = await internal.loginUser(request.body.username, request.body.password);
if (!login.success) return response.json(login);
const password_match = await bcrypt.compare(request.body.password, login.data.password);
if (!password_match) return { success: false, message: "Incorrect password" };
if (!password_match) return response.json({ success: false, message: "Incorrect password" });
request.session.user = { username: login.data.username, id: login.data.id };
response.json({ success: true });

View File

@ -1,14 +1,40 @@
const persistent_setting = require("node-persist");
persistent_setting.init({ dir: "data/" });
persistent_setting.init({ dir: "data/site/" });
const setupComplete = async () => (await persistent_setting.getItem("SETUP_COMPLETE")) || false;
const userRegistrationAllowed = async () => {
const setting = await persistent_setting.getItem("REGISTRATION_ALLOWED");
if (typeof setting == "undefined") return true;
console.log(setting);
return setting == "true";
let settings = {
SETUP_COMPLETE: false,
ACCOUNT_REGISTRATION: false,
BLOG_UPLOADING: false,
USER_MINIMUM_PASSWORD_LENGTH: 6,
};
const setSetupComplete = async () => await persistent_setting.setItem("SETUP_COMPLETE", "true");
const setUserRegistrationAllowed = (new_value) => persistent_setting.setItem("REGISTRATION_ALLOWED", String(new_value));
module.exports = { setupComplete, userRegistrationAllowed, setSetupComplete, setUserRegistrationAllowed };
async function act(key, value) {
// Change value if we have a value field
if (value) {
// Just incase the value is a string instead of a boolean
value = String(value).toLowerCase() === "true";
await persistent_setting.setItem(key, value);
settings[key] = value;
}
// Return the current setting
return settings[key];
}
function getSettings() {
return settings;
}
// Initialize our settings
setTimeout(async () => {
for (let i = 0; Object.keys(settings).length > i; i++) {
const setting_title = Object.keys(settings)[i];
const setting_value = await persistent_setting.getItem(setting_title);
settings[setting_title] = setting_value == true || setting_value == "true";
}
}, 3000);
module.exports = { act, getSettings };

View File

@ -42,6 +42,11 @@
width: 100%;
margin-bottom: 10px;
}
.e-image-area .placeholder {
margin: auto;
grid-row: 1/-1;
grid-column: 1/-1;
}
.e-image-area .image {
height: 100px;
aspect-ratio: 16/9;

View File

@ -49,6 +49,12 @@ $background-body: #222;
width: 100%;
margin-bottom: 10px;
.placeholder {
margin: auto;
grid-row: 1 / -1;
grid-column: 1 / -1;
}
.image {
height: 100px;
aspect-ratio: 16/9;

View File

@ -23,9 +23,7 @@
</div>
<div class="e-image-area">
<div class="image">
<img src="/img/.dev/screenshot.png" />
</div>
<div class="placeholder">Drop images here</div>
</div>
<div class="e-content">