diff --git a/backend/core/core.js b/backend/core/core.js index a7f09f1..fdb0745 100644 --- a/backend/core/core.js +++ b/backend/core/core.js @@ -80,7 +80,7 @@ async function newUser({ username, password, role } = {}) { // Master user was created; server initialized editSetting({ name: "SETUP_COMPLETE", value: true }); } -async function getUser({ user_id, username }) { +async function getUser({ user_id, username, include_password = false }) { if (!username && !user_id) return _r(false, "Either a user_id or username is needed."); let user; @@ -89,7 +89,11 @@ async function getUser({ user_id, username }) { else if (username) user = await prisma.user.findUnique({ where: { username: username } }); if (!user) return _r(false, "No matching user"); - else return { success: true, data: user }; + + // Delete the password from responses + if (!include_password) delete user.password; + + return { success: true, data: user }; } async function editUser({ requester_id, user_id, user_content }) { let user = await getUser({ user_id: user_id }); @@ -120,11 +124,15 @@ async function deleteUser({ user_id }) { // Posts async function newPost({ requester_id }) { - // const user = await getUser({ id: requester_id }); - const post = await prisma.post.create({ data: { owner: { connect: { id: requester_id } } } }); - // TODO: Validate request (Does user have perms?) // TODO: Does server allow new posts? + + // Find if user already has a draft + let existing_post = await prisma.post.findFirst({ where: { owner: { id: requester_id }, visibility: "DRAFT" } }); + if (existing_post) return existing_post.id; + + const post = await prisma.post.create({ data: { owner: { connect: { id: 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 } = {}) { diff --git a/backend/core/internal_api.js b/backend/core/internal_api.js index 5ecc1d9..9afd1ec 100644 --- a/backend/core/internal_api.js +++ b/backend/core/internal_api.js @@ -24,7 +24,7 @@ async function postLogin(req, res) { const { username, password } = req.body; // Get the username and password from the request body // Get the user by username - const existing_user = await core.getUser({ username: username }); + const existing_user = await core.getUser({ username: username, include_password: true }); if (!existing_user.success) return res.json({ success: false, message: existing_user.message }); // Check the password diff --git a/backend/page_scripts.js b/backend/page_scripts.js index d2def9b..b85a3ef 100644 --- a/backend/page_scripts.js +++ b/backend/page_scripts.js @@ -1,12 +1,16 @@ const external = require("./core/external_api"); const core = require("./core/core"); -function getThemePage(page_name) { +function _getThemePage(page_name) { return `themes/${core.settings.theme}/ejs/${page_name}.ejs`; } -function getDefaults(req) { +async function getDefaults(req) { // TODO: Fix reference to website_name - return { logged_in_user: req.session.user, website_name: core.settings.WEBSITE_NAME || "Yet-Another-Blog", settings: core.settings }; + let user; + if (req.session.user) user = await core.getUser({ user_id: req.session.user.id }); + if (user?.success) user = user.data; + console.log(user); + return { logged_in_user: user, website_name: core.settings.WEBSITE_NAME || "Yet-Another-Blog", settings: core.settings }; } async function index(request, response) { // Check if the master admin has been created @@ -22,8 +26,8 @@ async function index(request, response) { post.publish_date = formatted_date; }); - response.render(getThemePage("index"), { - ...getDefaults(request), + response.render(_getThemePage("index"), { + ...(await getDefaults(request)), blog_list: blog_list.data, pagination: blog_list.pagination, current_page: request.query.page || 0, @@ -31,11 +35,11 @@ async function index(request, response) { tags: tags, }); } -function register(request, response) { - response.render(getThemePage("register"), getDefaults(request)); +async function register(request, response) { + response.render(_getThemePage("register"), await getDefaults(request)); } -function login(request, response) { - response.render(getThemePage("login"), getDefaults(request)); +async function login(request, response) { + response.render(_getThemePage("login"), await getDefaults(request)); } async function author(req, res) { const user = await core.getUser({ user_id: req.params.author_id }); @@ -43,15 +47,14 @@ async function author(req, res) { if (!user.success) return res.redirect("/"); const profile = await core.getBiography({ author_id: user.data.id }); // TODO: Check for success - // const posts = await core.getBlog({ owner_id: user.data.id, raw: true }); const posts = await core.getPost({ requester_id: user.data.id }); - res.render(getThemePage("author"), { ...getDefaults(req), post: { ...profile.data, post_count: posts.data.length } }); + res.render(_getThemePage("author"), { ...(await getDefaults(req)), post: { ...profile.data, post_count: posts.data.length } }); } async function authorEdit(request, response) { let author = await core.getBiography({ author_id: request.params.author_id }); if (!author.success) return response.redirect("/"); - response.render(getThemePage("authorEdit"), { ...getDefaults(request), profile: author.data }); + response.render(_getThemePage("authorEdit"), { ...(await getDefaults(request)), profile: author.data }); } async function blogList(req, res) { const blog_list = await core.getPost({ requester_id: req.session.user?.id }, { search: req.query.search, search_title: true, search_tags: true, search_content: true }); @@ -62,8 +65,8 @@ async function blogList(req, res) { post.publish_date = formatted_date; }); - res.render(getThemePage("postSearch"), { - ...getDefaults(req), + res.render(_getThemePage("postSearch"), { + ...(await getDefaults(req)), blog_list: blog_list.data, pagination: blog_list.pagination, current_page: req.query.page || 0, @@ -73,7 +76,7 @@ async function blogList(req, res) { async function blogSingle(req, res) { const blog = await core.getPost({ post_id: req.params.blog_id }); if (blog.success === false) return res.redirect("/"); - res.render(getThemePage("post"), { ...getDefaults(req), blog_post: blog.data }); + res.render(_getThemePage("post"), { ...(await getDefaults(req)), blog_post: blog.data }); } async function blogNew(request, response) { const new_post = await core.newPost({ requester_id: request.session.user.id }); @@ -81,7 +84,8 @@ async function blogNew(request, response) { } async function blogEdit(req, res) { let existing_blog = await core.getPost({ post_id: req.params.blog_id }); - if (existing_blog.success) existing_blog = existing_blog.data; // FIXME: Quickfix for .success/.data issue + if (!existing_blog.success) return res.redirect("/"); + existing_blog = existing_blog.data; let published_time_parts = new Date(existing_blog.publish_date).toLocaleTimeString([], { timeStyle: "short" }).slice(0, 4).split(":"); const formatted_time = `${published_time_parts[0].padStart(2, "0")}:${published_time_parts[1].padStart(2, "0")}`; @@ -91,10 +95,10 @@ async function blogEdit(req, res) { const formatted_date = `${published_date_parts[2]}-${published_date_parts[0].padStart(2, "0")}-${published_date_parts[1].padStart(2, "0")}`; existing_blog.publish_date = formatted_date; - res.render(getThemePage("postNew"), { ...getDefaults(req), existing_blog: existing_blog }); + res.render(_getThemePage("postNew"), { ...(await getDefaults(req)), existing_blog: existing_blog }); } async function admin(request, response) { - response.render(getThemePage("admin-settings"), { ...getDefaults(request) }); + response.render(_getThemePage("admin-settings"), { ...(await getDefaults(request)) }); } async function atom(req, res) { res.type("application/xml"); diff --git a/frontend/views/blogNew.ejs b/frontend/views/blogNew.ejs deleted file mode 100644 index a446a0d..0000000 --- a/frontend/views/blogNew.ejs +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - <%= website_name %> | New Blog - - - <%- include("partials/header.ejs", {selected: 'home'}) %> - -
-
-
- <%if(existing_blog?.thumbnail) {%> - - <%} else {%> - - <% } %> -
-
- - -
-
- -
- <% if(existing_blog.raw_images?.length) { %> <% for (image in existing_blog.raw_images) {%> -
- -
X
-
- <%}%> <% } else {%> -
Drop images here
- <% } %> -
- -
-
- -
- - -
-
- -
-
- -
-
-
-
Publish On
- <% if(existing_blog.publish_date) {%> - - <%} else { %> - - <% } %> - - <% if(existing_blog.publish_date) {%> - - <%} else { %> - - <% } %> -
-
-
-
- - <% if(existing_blog.id){%> - - <% } else {%> - - <% } %> -
-
-
- - <%- include("partials/footer.ejs") %> - - - - diff --git a/frontend/views/partials/blog-entry.ejs b/frontend/views/partials/blog-entry.ejs deleted file mode 100644 index 9062063..0000000 --- a/frontend/views/partials/blog-entry.ejs +++ /dev/null @@ -1,16 +0,0 @@ -
- - - -
- -
<%= post.description %>
-
-
<%= post.publish_date.toLocaleString('en-US', { dateStyle:'medium'}) %>
- Read this post -> -
-
-
diff --git a/frontend/views/themes/default/ejs/partials/header.ejs b/frontend/views/themes/default/ejs/partials/header.ejs index 3a6ca0e..fbb9070 100644 --- a/frontend/views/themes/default/ejs/partials/header.ejs +++ b/frontend/views/themes/default/ejs/partials/header.ejs @@ -9,6 +9,7 @@ Posts + <% if (logged_in_user) { %> Account @@ -18,6 +19,12 @@ Login <% } %> <% } %> + + <% if (logged_in_user?.role == 'ADMIN') { %> + + Admin + + <% } %> diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 36a38ff..1f7976e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,7 +30,7 @@ model Post { description String? content String? media String[] - visibility PostStatus @default(UNLISTED) + visibility PostStatus @default(DRAFT) owner User? @relation(fields: [ownerid], references: [id], onDelete: Cascade) ownerid String? @@ -81,6 +81,7 @@ enum Role { } enum PostStatus { + DRAFT PRIVATE UNLISTED PUBLISHED