1
0
Fork 0
mirror of https://git.sr.ht/~roxwize/mipilin synced 2025-01-31 02:53:36 +00:00
Signed-off-by: roxwize <rae@roxwize.xyz>
This commit is contained in:
Rae 5e 2025-01-28 23:31:31 -05:00
parent 65c29b0564
commit ccc894dc33
Signed by: rae
GPG key ID: 5B1A0FAB9BAB81EE
10 changed files with 111 additions and 41 deletions

View file

@ -59,7 +59,12 @@ object-src 'none'; base-uri 'none';"
return next(); return next();
}); });
app.use((req, res, next) => { app.use((req, res, next) => {
console.log(`${req.ip.padEnd(24)} ${req.method.padStart(8)} ${req.path}`); let s = "";
for (const [k, v] of Object.entries(req.query))
s += `${k}=${v}&`;
s = s.slice(0, -1);
console.log(`${req.ip.padEnd(24)} ${req.method.padStart(8)} ${req.path}${s ? "?" + s : ""}`);
return next(); return next();
}) })

View file

@ -8,7 +8,13 @@ import {
users users
} from "../db/schema.js"; } from "../db/schema.js";
import { and, desc, eq, ne } from "drizzle-orm"; import { and, desc, eq, ne } from "drizzle-orm";
import { getMoods, render, render404, UserStatus, validateUrl } from "./util.js"; import {
getMoods,
render,
render404,
UserStatus,
validateUrl
} from "./util.js";
import { PgColumn } from "drizzle-orm/pg-core"; import { PgColumn } from "drizzle-orm/pg-core";
import dayjs from "dayjs"; import dayjs from "dayjs";
@ -84,9 +90,13 @@ export default async function (app: Express, db: NodePgDatabase) {
}) })
.from(journalEntries) .from(journalEntries)
.where( .where(
user.id === req.session["uid"] || req.session["status"] & UserStatus.MODERATOR user.id === req.session["uid"] ||
req.session["status"] & UserStatus.MODERATOR
? eq(journalEntries.user, user.id) ? eq(journalEntries.user, user.id)
: and(eq(journalEntries.user, user.id), ne(journalEntries.visibility, 0)) : and(
eq(journalEntries.user, user.id),
ne(journalEntries.visibility, 0)
)
) )
.orderBy(desc(journalEntries.date)) .orderBy(desc(journalEntries.date))
.limit(5) .limit(5)
@ -139,11 +149,6 @@ export default async function (app: Express, db: NodePgDatabase) {
res.redirect("/login"); res.redirect("/login");
return; return;
} }
if (!validateUrl(req.body.website)) {
req.flash("error", "The website URL provided is invalid or malformed.");
res.redirect(req.get("Referrer") || "/");
return;
}
const { uname } = ( const { uname } = (
await db await db
.select({ uname: users.name }) .select({ uname: users.name })
@ -154,20 +159,50 @@ export default async function (app: Express, db: NodePgDatabase) {
(uname || "") !== req.session["user"] && (uname || "") !== req.session["user"] &&
!(req.session["status"] & UserStatus.MODERATOR) !(req.session["status"] & UserStatus.MODERATOR)
) { ) {
res.redirect(req.get("Referrer") || "/"); render404(db, res, req);
return; return;
} }
await db if (req.query.param && (req.session["status"] & UserStatus.MODERATOR)) {
.update(profiles) switch (req.query.param) {
.set({ case "status":
// @ts-expect-error if (!req.query.status) {
bio: req.body.bio, req.flash("error", "No status parameter specified.");
website: req.body.website res.redirect(req.get("Referrer") || "/");
}) return;
.where(eq(profiles.user, req.session["uid"])); }
req.flash("success", "Profile updated!"); await db.update(users).set({
res.redirect("/dashboard"); // @ts-expect-error
status: parseInt(req.query.status)
}).where(eq(users.name, req.params.user));
break;
default:
render404(db, res, req);
return;
}
} else {
if (!validateUrl(req.body.website)) {
req.flash(
"error",
"The website URL provided is invalid or malformed."
);
res.redirect(req.get("Referrer") || "/");
return;
}
await db
.update(profiles)
.set({
// @ts-expect-error
bio: req.body.bio,
website: req.body.website
})
.where(eq(profiles.user, req.session["uid"]));
req.flash("success", "Profile updated!");
res.redirect("/dashboard");
return;
}
req.flash("success", "Updated");
res.redirect(req.get("Referrer") || "/");
}); });
app.post("/users/:user/follow", async (req, res) => { app.post("/users/:user/follow", async (req, res) => {
if (!req.session["loggedIn"]) { if (!req.session["loggedIn"]) {

20
static/js/admin.js Normal file
View file

@ -0,0 +1,20 @@
const e_user_selected = document.getElementById("user-selected");
let current;
document.querySelectorAll("#users tr").forEach((el) => {
el.addEventListener("click", () => {
current = el.querySelector("td:nth-child(2)").textContent;
e_user_selected.textContent = current;
});
});
document.querySelectorAll("button").forEach((el) => {
el.addEventListener("click", (ev) => {
if (!current) {
ev.preventDefault();
return;
};
const e = el.parentElement;
e.setAttribute("action", el.parentElement.dataset.url.replaceAll("{}", current));
});
});

View file

@ -1,14 +0,0 @@
mixin feed(feed, hideUser)
if feed.length > 0
#feed
for update of feed
.feed-update
div
a(href=`/users/${update.user}`)
if !hideUser
| #{update.user}
strong= update.mood
div= update.desc || "[no mood description provided]"
div(title=update.date.toLocaleString())= update.relativeDate
else
span [no updates]

View file

@ -1,3 +1,18 @@
mixin feed(feed, hideUser)
if feed.length > 0
#feed
for update of feed
.feed-update
div
a(href=`/users/${update.user}`)
if !hideUser
| #{update.user}
strong= update.mood
div= update.desc || "[no mood description provided]"
div(title=update.date.toLocaleString())= update.relativeDate
else
span [no updates]
mixin invite_code_expiration(code) mixin invite_code_expiration(code)
- const timestamp = code.expires.getTime() - const timestamp = code.expires.getTime()
if timestamp === 0 if timestamp === 0

View file

@ -5,7 +5,10 @@ block content
h1 Admin Panel h1 Admin Panel
p Don't Be Evil p Don't Be Evil
h2 Users h2 Users
table p
| Selected:
strong#user-selected [none]
table#users
tbody tbody
tr tr
th UID th UID
@ -17,7 +20,13 @@ block content
td td
a(href=`/users/${user.uname}`)= user.uname a(href=`/users/${user.uname}`)= user.uname
td= user.status.toString(2).padStart(4, "0") td= user.status.toString(2).padStart(4, "0")
h2 Invite codes br
form(action="#", method="post", data-url="/users/{}/edit?param=status&status=4")
button#btn-trust Trust
button#btn-ban Ban
form(action="#", method="post", data-url="/users/{}/edit?param=status&status=0")
button#btn-reset Revoke all stati
h2(style="margin-top:1em;") Invite codes
p Well Rae. You've made quite a The Closed Beta. p Well Rae. You've made quite a The Closed Beta.
form(action="/codes/delete", method="post") form(action="/codes/delete", method="post")
table table
@ -41,3 +50,4 @@ block content
form(action="/codes/create", method="post") form(action="/codes/create", method="post")
input(type="datetime-local", name="expiration") input(type="datetime-local", name="expiration")
button(type="submit") Create button(type="submit") Create
script(src="/js/admin.js", nonce=nonce)

View file

@ -39,7 +39,7 @@ block content
| / | /
a(href="#invite-codes") Invite codes a(href="#invite-codes") Invite codes
p This is where you "MIPILIN"! That is all you need to know!!! p This is where you "MIPILIN"! That is all you need to know!!!
p If onlookers notice your actions and inquire about what you are doing, you MUST tell them that you are mipilining all over the place, and then PROMPTLY SCROLL DOWN AND GENERATE AN INVITE CODE SO THAT THEY CAN MIPILIN TOO. If you do not do this I will cry. p If onlookers notice your actions and inquire about what you are doing, you MUST tell them that you are mipilining all over the place, and then PROMPTLY SCROLL DOWN AND GENERATE AN INVITE CODE SO THAT THEY CAN MIPILIN TOO.
form#dashboard-update-form(action="/update/mood", method="post", onsubmit="disable(this);") form#dashboard-update-form(action="/update/mood", method="post", onsubmit="disable(this);")
select(name="mood", required) select(name="mood", required)
//- Maybe put the index of the mood in the value of the option element //- Maybe put the index of the mood in the value of the option element
@ -50,7 +50,6 @@ block content
button(type="submit") Update button(type="submit") Update
h1#feed(style="margin-top:0.5em;") Feed h1#feed(style="margin-top:0.5em;") Feed
include _feed.pug
+feed(recentUpdates) +feed(recentUpdates)
h1#invite-codes(style="margin-top:1em;") Invite codes h1#invite-codes(style="margin-top:1em;") Invite codes

View file

@ -1,4 +1,5 @@
extends site.pug extends site.pug
include _util.pug
block head block head
style style
@ -46,5 +47,4 @@ block content
| . | .
h1 Global Feed h1 Global Feed
p Look at how all these people are doing!!! p Look at how all these people are doing!!!
include _feed.pug
+feed(feedUpdates) +feed(feedUpdates)

View file

@ -35,7 +35,7 @@ html(lang="en")
| You should log in! It's FUN!! | You should log in! It's FUN!!
span#ticker-marquee span#ticker-marquee
marquee marquee
| The beta is still a thing that is happening! If something fucks up plz let me know! <3 | The beta is still a thing that is happening! If something fucks up plz let me know! &lt;3
#page #page
block page block page
#content #content

View file

@ -1,4 +1,5 @@
extends site.pug extends site.pug
include _util.pug
//- Display mood here but keep yourself dry (i.e. dont request user mood if the profile being viewed is the profile of the currently logged-in user) //- Display mood here but keep yourself dry (i.e. dont request user mood if the profile being viewed is the profile of the currently logged-in user)
block content block content
@ -47,5 +48,4 @@ block content
div [no entries] div [no entries]
br br
h2 Recent mood updates h2 Recent mood updates
include _feed.pug
+feed(userMoodFeed, true) +feed(userMoodFeed, true)