diff --git a/f0ck.sql b/f0ck.sql index 625ca3e..819d60f 100644 --- a/f0ck.sql +++ b/f0ck.sql @@ -131,7 +131,7 @@ CREATE TABLE public."user" ( login character varying(255) NOT NULL, "user" character varying(255) NOT NULL, password character varying(167) NOT NULL, - level integer NOT NULL + admin boolean NOT NULL ); ALTER TABLE public."user" OWNER TO f0ck; diff --git a/public/s/js/admin.js b/public/s/js/admin.js index 5384894..6e1c9ff 100644 --- a/public/s/js/admin.js +++ b/public/s/js/admin.js @@ -333,7 +333,8 @@ const flash = ({ type, msg }) => { document.querySelector("a#a_toggle").addEventListener("click", toggleEvent); [...document.querySelectorAll("#tags > .badge > a:first-child")].map(t => t.addEventListener("click", editTagEvent)); [...document.querySelectorAll("#tags > .badge > a:last-child")].map(t => t.addEventListener("click", deleteEvent)); - document.querySelector("svg#a_delete").addEventListener("click", deleteButtonEvent); + if(document.querySelector("svg#a_delete")) + document.querySelector("svg#a_delete").addEventListener("click", deleteButtonEvent); document.querySelector("svg#a_favo").addEventListener("click", toggleFavEvent); document.addEventListener("keyup", e => { diff --git a/src/inc/config.mjs b/src/inc/config.mjs index ee7c7e0..b45a2ea 100644 --- a/src/inc/config.mjs +++ b/src/inc/config.mjs @@ -1,4 +1,4 @@ -import _config from "../../config.json" assert { type: "json" }; +import _config from "../../config.json" with { type: "json" }; let config = JSON.parse(JSON.stringify(_config)); diff --git a/src/inc/lib.mjs b/src/inc/lib.mjs index 707a0de..45aa0d2 100644 --- a/src/inc/lib.mjs +++ b/src/inc/lib.mjs @@ -134,15 +134,6 @@ export default new class { const derivedKey = await scrypt(str, salt, 64); return crypto.timingSafeEqual(keyBuffer, derivedKey); }; - async auth(req, res, next) { - if(!req.session) { - return res.reply({ - code: 401, - body: "401 - Unauthorized" - }); - } - return next(); - }; async getTags(itemid) { const tags = await db` select "tags".id, "tags".tag, "tags".normalized, "user".user @@ -217,6 +208,27 @@ export default new class { TABLE_NAME='user_options' and COLUMN_NAME = 'avatar' `)[0].avatar; - } + }; + + // meddlware + async auth(req, res, next) { + if(!req.session || !req.session.admin) { + return res.reply({ + code: 401, + body: "401 - Unauthorized" + }); + } + return next(); + }; + + async loggedin(req, res, next) { + if(!req.session) { + return res.reply({ + code: 401, + body: "401 - Unauthorized" + }); + } + return next(); + }; }; diff --git a/src/inc/routeinc/f0cklib.mjs b/src/inc/routeinc/f0cklib.mjs index 38ab8e0..aabab30 100644 --- a/src/inc/routeinc/f0cklib.mjs +++ b/src/inc/routeinc/f0cklib.mjs @@ -7,12 +7,13 @@ import url from "url"; const globalfilter = cfg.nsfp.map(n => `tag_id = ${n}`).join(' or '); export default { - getf0cks: async (o = { user, tag, mime, page, mode, fav, session }) => { + getf0cks: async (o = { user, tag, mime, page, mode, fav, session, limit }) => { const user = o.user ? decodeURI(o.user) : null; const tag = lib.parseTag(o.tag ?? null); const mime = o.mime ?? null; const page = +(o.page ?? 1); const smime = cfg.allowedMimes.includes(mime) ? mime + "/%" : mime === "" ? "%" : "%"; + const eps = o.limit ?? cfg.websrv.eps; const tmp = { user, tag, mime, smime, page, mode: o.mode }; const modequery = mime == "audio" ? lib.getMode(0) : lib.getMode(o.mode ?? 0); @@ -70,7 +71,7 @@ export default { group by items.id, tags.tag, ta.tag_id order by items.id desc offset ${offset} - limit ${cfg.websrv.eps} + limit ${eps} `; const cheat = []; diff --git a/src/inc/routes/admin.mjs b/src/inc/routes/admin.mjs index 436bf48..60ad38a 100644 --- a/src/inc/routes/admin.mjs +++ b/src/inc/routes/admin.mjs @@ -3,18 +3,7 @@ import lib from "../lib.mjs"; import { exec } from "child_process"; import { promises as fs } from "fs"; -const auth = async (req, res, next) => { - if(!req.session) { - return res.reply({ - code: 401, - body: "401 - Unauthorized" - }); - } - return next(); -}; - export default (router, tpl) => { - router.get(/^\/login(\/)?$/, async (req, res) => { if(req.cookies.session) { return res.reply({ @@ -72,7 +61,7 @@ export default (router, tpl) => { }).end(); }); - router.get(/^\/logout$/, auth, async (req, res) => { + router.get(/^\/logout$/, lib.loggedin, async (req, res) => { const usersession = await db` select * from "user_sessions" @@ -103,7 +92,7 @@ export default (router, tpl) => { }); }); - router.get(/^\/admin(\/)?$/, auth, async (req, res) => { // frontpage + router.get(/^\/admin(\/)?$/, lib.auth, async (req, res) => { // frontpage res.reply({ body: tpl.render("admin", { @@ -114,7 +103,7 @@ export default (router, tpl) => { }); }); - router.get(/^\/admin\/sessions(\/)?$/, auth, async (req, res) => { + router.get(/^\/admin\/sessions(\/)?$/, lib.auth, async (req, res) => { const rows = await db` select "user_sessions".*, "user".user from "user_sessions" @@ -132,7 +121,7 @@ export default (router, tpl) => { }); }); - router.get(/^\/admin\/log(\/)?$/, auth, async (req, res) => { + router.get(/^\/admin\/log(\/)?$/, lib.auth, async (req, res) => { exec("journalctl -qeu f0ck --no-pager", (err, stdout) => { res.reply({ body: tpl.render("admin/log", { @@ -143,7 +132,7 @@ export default (router, tpl) => { }); }); - router.get(/^\/admin\/recover\/?/, auth, async (req, res) => { + router.get(/^\/admin\/recover\/?/, lib.auth, async (req, res) => { if(req.url.qs?.id) { const id = +req.url.qs.id; const f0ck = await db` diff --git a/src/inc/routes/apiv2/index.mjs b/src/inc/routes/apiv2/index.mjs index c58e7c2..7fec014 100644 --- a/src/inc/routes/apiv2/index.mjs +++ b/src/inc/routes/apiv2/index.mjs @@ -139,7 +139,7 @@ export default router => { // tags lol - group.put(/\/admin\/tags\/(?.*)/, lib.auth, async (req, res) => { + group.put(/\/admin\/tags\/(?.*)/, lib.loggedin, async (req, res) => { if(!req.params.tagname || !req.post.newtag) { return res.json({ success: false, @@ -187,7 +187,7 @@ export default router => { return res.json(q, tagname === newtag ? 200 : 201); // created (modified) }); - group.get(/\/admin\/tags\/suggest$/, lib.auth, async (req, res) => { + group.get(/\/admin\/tags\/suggest$/, lib.loggedin, async (req, res) => { const reply = { success: false, suggestions: {} @@ -267,7 +267,7 @@ export default router => { }); }); - group.post(/\/admin\/togglefav$/, lib.auth, async (req, res) => { + group.post(/\/admin\/togglefav$/, lib.loggedin, async (req, res) => { const postid = +req.post.postid; let favs = await db` diff --git a/src/inc/routes/apiv2/settings.mjs b/src/inc/routes/apiv2/settings.mjs index dfea483..e0ff897 100644 --- a/src/inc/routes/apiv2/settings.mjs +++ b/src/inc/routes/apiv2/settings.mjs @@ -3,7 +3,7 @@ import lib from '../../lib.mjs'; export default router => { router.group(/^\/api\/v2\/settings/, group => { - group.put(/\/setAvatar/, lib.auth, async (req, res) => { + group.put(/\/setAvatar/, lib.loggedin, async (req, res) => { if(!req.post.avatar) { return res.json({ msg: 'no avatar provided', diff --git a/src/inc/routes/apiv2/tags.mjs b/src/inc/routes/apiv2/tags.mjs index b551576..fa0d4b3 100644 --- a/src/inc/routes/apiv2/tags.mjs +++ b/src/inc/routes/apiv2/tags.mjs @@ -3,7 +3,7 @@ import lib from '../../lib.mjs'; export default router => { router.group(/^\/api\/v2\/admin\/(?\d+)\/tags/, group => { - group.get(/$/, lib.auth, async (req, res) => { + group.get(/$/, lib.loggedin, async (req, res) => { // get tags if(!req.params.postid) { return res.json({ @@ -18,7 +18,7 @@ export default router => { }); }); - group.post(/$/, lib.auth, async (req, res) => { + group.post(/$/, lib.loggedin, async (req, res) => { // assign and/or create tag if(!req.params.postid || !req.post.tagname) { return res.json({ @@ -80,7 +80,7 @@ export default router => { }); }); - group.put(/\/toggle$/, lib.auth, async (req, res) => { + group.put(/\/toggle$/, lib.loggedin, async (req, res) => { // xD if(!req.params.postid) { return res.json({ diff --git a/src/inc/routes/index.mjs b/src/inc/routes/index.mjs index c15b934..9d936dc 100644 --- a/src/inc/routes/index.mjs +++ b/src/inc/routes/index.mjs @@ -14,7 +14,7 @@ export default (router, tpl) => { const user = decodeURIComponent(req.params.user); const query = await db` - select "user".user, "user".created_at, user_options.* + select "user".user, "user".admin, "user".created_at, user_options.* from user_options left join "user" on "user".id = user_options.user_id where "user".user ilike ${user} @@ -31,31 +31,42 @@ export default (router, tpl) => { }); } - const f0cks = await f0cklib.getf0cks({ - user: user, - mode: req.session.mode, - fav: false, - session: !!req.session - }); - const favs = await f0cklib.getf0cks({ - user: user, - mode: req.session.mode, - fav: true, - session: !!req.session - }); - + let f0cks, favs; const count = { f0cks: 0, favs: 0 }; - - if('items' in f0cks) { - count.f0cks = f0cks.items.length; - f0cks.items = f0cks.items.slice(0, 50); + try { + f0cks = await f0cklib.getf0cks({ + user: user, + mode: req.session.mode, + fav: false, + session: !!req.session, + limit: 99999999 + }); + if('items' in f0cks) { + count.f0cks = f0cks.items.length; + f0cks.items = f0cks.items.slice(0, 50); + } + } catch(err) { + f0cks = false; + count.f0cks = 0; } - if('items' in favs) { - count.favs = favs.items.length; - favs.items = favs.items.slice(0, 50); + try { + favs = await f0cklib.getf0cks({ + user: user, + mode: req.session.mode, + fav: true, + session: !!req.session, + limit: 99999999 + }); + if('items' in favs) { + count.favs = favs.items.length; + favs.items = favs.items.slice(0, 50); + } + } catch(err) { + favs = false; + count.favs = 0; } const data = { @@ -100,7 +111,7 @@ export default (router, tpl) => { }); }); - router.get(/^\/mode\/(\d)/, auth, async (req, res) => { + router.get(/^\/mode\/(\d)/, lib.loggedin, async (req, res) => { const mode = +req.url.split[1]; let referertmp = req.headers.referer; let referer = ""; diff --git a/src/inc/routes/picdump.mjs b/src/inc/routes/picdump.mjs new file mode 100644 index 0000000..d37036f --- /dev/null +++ b/src/inc/routes/picdump.mjs @@ -0,0 +1,26 @@ +import db from "../../inc/sql.mjs"; +import cfg from "../../inc/config.mjs"; +import f0cklib from "../routeinc/f0cklib.mjs"; + +export default (router, tpl) => { + router.get(/^\/picdump$/, async (req, res) => { + const dump = await db` + SELECT * + FROM items + WHERE ( + to_timestamp(stamp) >= date_trunc('week', CURRENT_TIMESTAMP - interval '1 week') AND + to_timestamp(stamp) < date_trunc('week', CURRENT_TIMESTAMP) + ) AND + mime LIKE 'image/%' + ORDER BY stamp DESC + `; + + res.reply({ + body: tpl.render('picdump', { + dump, + tmp: null + }, req) + }); + }); + return router; +}; diff --git a/src/inc/routes/ranking.mjs b/src/inc/routes/ranking.mjs index 4cafc46..48da3e3 100644 --- a/src/inc/routes/ranking.mjs +++ b/src/inc/routes/ranking.mjs @@ -8,13 +8,13 @@ export default (router, tpl) => { try { const list = await db` select - "user".user, + "user".user, "user".admin, coalesce("user_options".avatar, ${await lib.getDefaultAvatar()}) as avatar, count(distinct(tag_id, item_id)) as count from "tags_assign" left join "user" on "user".id = "tags_assign".user_id left join "user_options" on "user_options".user_id = "user".id - group by "user".user, "user_options".avatar + group by "user".user, "user_options".avatar, "user".admin order by count desc `; const stats = await lib.countf0cks(); diff --git a/src/inc/routes/search.mjs b/src/inc/routes/search.mjs index 5ffad83..45d3aa1 100644 --- a/src/inc/routes/search.mjs +++ b/src/inc/routes/search.mjs @@ -5,7 +5,7 @@ import search from "../routeinc/search.mjs"; const _eps = 20; export default (router, tpl) => { - router.get(/^\/search(\/)?$/, lib.auth, async (req, res) => { + router.get(/^\/search(\/)?$/, lib.loggedin, async (req, res) => { let ret; let tag = req.url.qs.tag ?? []; let page = req.url.qs.page ?? 1; diff --git a/src/inc/trigger/parser.mjs b/src/inc/trigger/parser.mjs index 5a2fc51..10d22c2 100644 --- a/src/inc/trigger/parser.mjs +++ b/src/inc/trigger/parser.mjs @@ -211,6 +211,19 @@ export default async bot => { await fs.promises.copyFile(source, `./public/b/${filename}`); await fs.promises.unlink(source).catch(_=>{}); + // user alias + let username = e.user.nick || e.user.username; + const alias = (await db` + select "user"."user" + from "user_alias" + join "user" on "user".id = user_alias.userid + where lower(user_alias.alias) ilike ${username} + limit 1 + `)?.[0]?.user; + if(alias) { + username = alias; + } + await db` insert into items ${ db({ @@ -219,7 +232,7 @@ export default async bot => { mime: mime, size: size, checksum: checksum, - username: e.user.nick || e.user.username, + username: username, userchannel: e.channel, usernetwork: e.network, stamp: ~~(new Date() / 1000), diff --git a/src/index.mjs b/src/index.mjs index 5b04e8e..810178b 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -71,7 +71,7 @@ process.on('unhandledRejection', err => { if(req.cookies.session) { const user = await db` - select "user".id, "user".login, "user".user, "user".level, "user_sessions".id as sess_id, "user_options".* + select "user".id, "user".login, "user".user, "user".admin, "user_sessions".id as sess_id, "user_options".* from "user_sessions" left join "user" on "user".id = "user_sessions".user_id left join "user_options" on "user_options".user_id = "user_sessions".user_id diff --git a/views/index.html b/views/index.html index bba08b7..684016b 100644 --- a/views/index.html +++ b/views/index.html @@ -2,7 +2,7 @@
- @if(tmp.user)

user: {!! tmp.user.toLowerCase() !!}@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif

@endif + @if(tmp.user)

user: {!! tmp.user.toLowerCase() !!}@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif

@endif @if(tmp.tag)

tag: @if(session){!! tmp.tag.toLowerCase() !!}@else{!! tmp.tag.toLowerCase() !!}@endif@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif

@endif
@each(items as item) @@ -15,4 +15,4 @@
-@include(snippets/footer) \ No newline at end of file +@include(snippets/footer) diff --git a/views/item.html b/views/item.html index bc3ae41..318d22f 100644 --- a/views/item.html +++ b/views/item.html @@ -14,7 +14,7 @@
- + @if(session.admin)@endif
@endif
@@ -83,7 +83,7 @@ @if(typeof item.tags !== "undefined") @each(item.tags as tag) - {!! tag.tag !!}@if(session) ×@endif + {!! tag.tag !!}@if(session.admin) ×@endif @endeach @endif diff --git a/views/picdump.html b/views/picdump.html new file mode 100644 index 0000000..d00bc22 --- /dev/null +++ b/views/picdump.html @@ -0,0 +1,22 @@ +@include(snippets/header) +
+

Picdump (last week)

+
+ @each(dump as line) + + @endeach +
+
+ +@include(snippets/footer) diff --git a/views/ranking.html b/views/ranking.html index c8ac9f9..39bc6ad 100644 --- a/views/ranking.html +++ b/views/ranking.html @@ -11,8 +11,8 @@ @for(let i = 0; i < list.length; i++) {{ i + 1 }} - - {!! list[i].user !!} + + @if(list[i].admin)⭐ @endif{!! list[i].user !!} {{ list[i].count }} @endfor diff --git a/views/settings.html b/views/settings.html index e3da9ef..e402e73 100644 --- a/views/settings.html +++ b/views/settings.html @@ -1,7 +1,7 @@ @include(snippets/header)

Settings

- @if(session.avatar)@endif + @if(session.avatar)@endif

Account

@@ -10,8 +10,8 @@ - - + + @@ -19,7 +19,14 @@ - + + + + + + + +
{{ session.id }}
level{{ session.level }}/100admin{{ !!session.admin }}
username
avatar
mail
diff --git a/views/snippets/navbar.html b/views/snippets/navbar.html index 94b3d23..d3dea70 100644 --- a/views/snippets/navbar.html +++ b/views/snippets/navbar.html @@ -5,14 +5,14 @@