diff --git a/backend/core/core.js b/backend/core/core.js index 0c35ea1..dd77715 100644 --- a/backend/core/core.js +++ b/backend/core/core.js @@ -140,28 +140,6 @@ async function newPost({ requester_id }) { return post.id; } async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {}, { search, search_title, search_content, search_tags } = {}, { limit = 10, page = 0, pagination = true } = {}) { - // Get a single post - if (post_id) { - let post; - post = await prisma.post.findUnique({ where: { id: post_id }, include: { owner: true, tags: true } }); - if (!post) return _r(false, "Post does not exist"); - post = _stripPrivatePost(post); - - // Tags - let post_tags = []; - post.raw_tags = []; - post.tags.forEach((tag) => { - post_tags.push(tag.name); - post.raw_tags.push(); - }); - post.tags = post_tags; - - // Render post - return { success: true, data: await _renderPost(post) }; - } - - // Otherwise build WHERE_OBJECT using data we do have - let post_list = []; let where_object = { OR: [ // Standard discovery: Public, and after the publish date @@ -190,6 +168,46 @@ async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {}, }, ], }; + + // Admins can view everything at any point + let user; + if (requester_id) { + user = await getUser({ user_id: requester_id }); + if (user.success) user = user.data; + if (user.role === "ADMIN") where_object["OR"].push({ NOT: { id: "" } }); + } + + // Get a single post + if (post_id) { + let post; + + // We can view unlisted posts, but we don't want them to show up otherwise in search. + // Inject a "unlisted" inclusion into where_object to allow direct viewing of unlisted posts + where_object["OR"].push({ visibility: "UNLISTED" }); + + // Allow getting drafts if the requesting user owns the draft + where_object["OR"].push({ AND: [{ visibility: "DRAFT" }, { ownerid: requester_id }] }); + + post = await prisma.post.findUnique({ where: { ...where_object, id: post_id }, include: { owner: true, tags: true } }); + if (!post) return _r(false, "Post does not exist"); + post = _stripPrivatePost(post); + + // Tags + let post_tags = []; + post.raw_tags = []; + post.tags.forEach((tag) => { + post_tags.push(tag.name); + post.raw_tags.push(); + }); + post.tags = post_tags; + + // Render post + return { success: true, data: await _renderPost(post) }; + } + + // Otherwise build WHERE_OBJECT using data we do have + let post_list = []; + // Build the "where_object" object if (search) { if (search_tags) where_object["AND"][0]["OR"].push({ tags: { some: { name: search?.toLowerCase() } } }); @@ -599,7 +617,7 @@ async function postSetting(key, value) { async function editSetting({ name, value }) { if (!Object.keys(settings).includes(name)) return _r(false, "Setting is not valid"); - await prisma.setting.upsert({ where: { id: key }, update: { value: value }, create: { id: key, value: value } }); + await prisma.setting.upsert({ where: { id: name }, update: { value: value }, create: { id: name, value: value } }); try { settings[key] = JSON.parse(value); } catch { diff --git a/backend/core/internal_api.js b/backend/core/internal_api.js index 51ee1f2..eb219e0 100644 --- a/backend/core/internal_api.js +++ b/backend/core/internal_api.js @@ -5,7 +5,7 @@ const validate = require("../form_validation"); async function postRegister(req, res) { const { username, password } = req.body; // Get the username and password from the request body - const form_validation = await validate.registerUser(username, password); // Check form for errors + const form_validation = await validate.newUser({ username: username, password: password }); // Check form for errors // User registration disabled? // We also check if the server was setup. If it was not set up, the server will proceed anyways. diff --git a/backend/form_validation.js b/backend/form_validation.js index 3e5f38c..3f36dff 100644 --- a/backend/form_validation.js +++ b/backend/form_validation.js @@ -5,10 +5,10 @@ // Format given data in an accessible way // -const core = require("./core/core"); - // Make sure the user registration data is safe and valid. function newUser({ username, password } = {}) { + const core = require("./core/core"); // HACK: Need to require the core module here because the settings don't get set otherwise. + if (!username) return _r(false, "No username provided"); if (!password) return _r(false, "No password provided"); if (password.length < core.settings["USER_MINIMUM_PASSWORD_LENGTH"]) return _r(false, `Password is not long enough. Minimum length is ${core.settings["USER_MINIMUM_PASSWORD_LENGTH"]}`); diff --git a/backend/page_scripts.js b/backend/page_scripts.js index 96e6035..6e21d3f 100644 --- a/backend/page_scripts.js +++ b/backend/page_scripts.js @@ -75,7 +75,7 @@ async function blogList(req, res) { }); } async function blogSingle(req, res) { - const blog = await core.getPost({ post_id: req.params.blog_id }); + const blog = await core.getPost({ requester_id: req.session.user?.id, post_id: req.params.blog_id }); if (blog.success === false) return res.redirect("/"); res.render(_getThemePage("post"), { ...(await getDefaults(req)), blog_post: blog.data }); } diff --git a/backend/permissions.js b/backend/permissions.js index cbb57f8..a786b25 100644 --- a/backend/permissions.js +++ b/backend/permissions.js @@ -16,8 +16,14 @@ function patchPost(post_content, user) { return _r(false, "User is not permitted to preform action."); } function patchBiography(biography, user) { - // Biographies are just fancy posts right now. - return patchPost(biography, user); + // Admins can always update any post + if (user.role === "ADMIN") return _r(true); + + // User edits their own account + if (biography.id === user.id) return _r(true); + + // User is not permitted + return _r(false, "User is not permitted to preform action."); } function _r(s, m, d) {