From e5acf042d7fabc8d1d799a262108510c7a123648 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Sun, 17 Mar 2024 16:59:33 -0400 Subject: [PATCH] =?UTF-8?q?[=E2=9A=A1=EF=B8=8F]=20-=20Adding=20informal,?= =?UTF-8?q?=20expiring,=20password=20and=20plus=20pages=20and=20rules.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> --- apps/linkos/bun.lockb | Bin 64766 -> 66600 bytes apps/linkos/package.json | 2 + apps/linkos/src/assets/I.html | 82 +++++++++++++++++++++ apps/linkos/src/assets/password.html | 104 +++++++++++++++++++++++++++ apps/linkos/src/assets/plus.html | 90 +++++++++++++++++++++++ apps/linkos/src/http/api/LinkAPI.ts | 98 +++++++++++++++++++++---- apps/linkos/src/services/GetLink.ts | 1 + 7 files changed, 364 insertions(+), 13 deletions(-) create mode 100644 apps/linkos/src/assets/I.html create mode 100644 apps/linkos/src/assets/password.html create mode 100644 apps/linkos/src/assets/plus.html diff --git a/apps/linkos/bun.lockb b/apps/linkos/bun.lockb index 2d67bc64f57a81e34257a826bae7dbf63d9d6417..55288c5f3d28c8c79bf7a19f5674e819a7671ee6 100755 GIT binary patch delta 11446 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 DPa?s( delta 10344 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 + + + + + + {{ title }} + + + + +
+ + Links + +

{{ title }}

+
{{ description }}
+ + +
+ + + + \ No newline at end of file diff --git a/apps/linkos/src/assets/password.html b/apps/linkos/src/assets/password.html new file mode 100644 index 0000000..d79ebc9 --- /dev/null +++ b/apps/linkos/src/assets/password.html @@ -0,0 +1,104 @@ + + + + + + + {{ title }} + + + + +
+ + Links + +

{{ title }}

+
+ +
{{ enter_password_text }}
+ + + +
+ +
+
+ + +
+ + + + \ No newline at end of file diff --git a/apps/linkos/src/assets/plus.html b/apps/linkos/src/assets/plus.html new file mode 100644 index 0000000..49bd4fd --- /dev/null +++ b/apps/linkos/src/assets/plus.html @@ -0,0 +1,90 @@ + + + + + + + {{ title }} + + + + +
+ + Links + +

{{ title }}

+
{{ description }}
+ + + + + +
+ + + + \ No newline at end of file diff --git a/apps/linkos/src/http/api/LinkAPI.ts b/apps/linkos/src/http/api/LinkAPI.ts index 59f7d9b..d2f9b40 100644 --- a/apps/linkos/src/http/api/LinkAPI.ts +++ b/apps/linkos/src/http/api/LinkAPI.ts @@ -9,7 +9,7 @@ import Log from "@/utils/Log.ts"; import Global from "@/utils/Global.ts"; import Env from "@/utils/Env.ts"; import ClickMessage from "@/models/ClickMessage.ts"; - +import nunjucks from 'nunjucks'; export default class LinkAPI { private static producer: Producer | false; @@ -27,31 +27,38 @@ export default class LinkAPI { return LinkAPI.getRedirect(c, true) } - private static async getRedirect(c: Context, qr: boolean = false) { + public static async getWithPassword(c: Context) { const {link} = c.req.param(); - try { - let shortLink: false | Link; + const body = await c.req.formData() + const password = body.get('password'); - const linkFormRedis = await RedisProvider.getClient().get(link); - if (linkFormRedis !== null) { - shortLink = Global.ParseOrFalse(linkFormRedis); - } else { - shortLink = await Link.getLink(link); + let shortLink = await LinkAPI.getLink(link); - await RedisProvider.getClient().set(link, JSON.stringify(shortLink)); - } + if (shortLink !== false && shortLink.password === password) { + return LinkAPI.redirect(shortLink.dest, c); + } + + return c.redirect(`${Env.MAIN_DOMAIN}/${link}`); + } + + private static async getRedirect(c: Context, qr: boolean = false) { + const {link} = c.req.param(); + + try { + let shortLink = await LinkAPI.getLink(link); if (shortLink) { await LinkAPI.missions(shortLink, qr, c); - return LinkAPI.redirect(this.appendQuery(shortLink.dest, c), c); + return LinkAPI.getLinkAction(shortLink, c, link); } } catch (e: any) { Log.debug(e); } - return c.html(await new Response(Bun.file(LinkAPI.path + "404.html")).text(), 404); + + return LinkAPI.its404(c); } public static async getPublic(c: Context) { @@ -82,6 +89,7 @@ export default class LinkAPI { const start = +new Date(); if (LinkAPI.producer) { + // TODO: check for informal, password, etc. await LinkAPI.producer.send({ topic : Analytics.TOPIC_CLICKHOUSE, messages: [{value: (new AnalyticsMessage(link.id, qr, c.req.header())).toString()}] @@ -114,4 +122,68 @@ export default class LinkAPI { } + private static async getLinkAction(link: Link, c: Context, linkId: string) { + if (link.expiring_link && link.expiration_date !== undefined) { + if (+new Date(link.expiration_date) < +new Date()) { + return LinkAPI.its404(c); + } + } + + if (link.password_protected) { + return c.html(LinkAPI.render('password', link)); + } else if (link.plus_enabled && linkId.endsWith('+')) { + return c.html(LinkAPI.render('plus', link)); + } else if (link.informal_redirection) { + return c.html(LinkAPI.render('i', link)); + } + + return LinkAPI.redirect(this.appendQuery(link.dest, c), c) + } + + private static async render(page: string, link: Link) { + const text = await (new Response(Bun.file(`${LinkAPI.path}${page}.html`))).text(); + + return nunjucks.renderString(text, LinkAPI.linksContext(link)); + + } + + + private static linksContext(link: Link) { + return { + // TODO: Make language dynamic + lang : 'en', + dir : 'lrt', + goto_text : 'Go to', + link_target_text : 'Link destination', + password_placeholder_text: 'e.g. Aa123456', + enter_password_text : 'Password is required to access this short link destination', + form_target : `${Env.MAIN_DOMAIN}/password/${link.id}`, + + + title : link.title, + description: link.description, + link : link.dest, + }; + } + + private static async getLink(linkID: string) { + linkID = linkID.replace(/\+$/, ''); + + let shortLink: false | Link = false; + + const linkFormRedis = await RedisProvider.getClient().get(linkID); + if (linkFormRedis !== null) { + shortLink = Global.ParseOrFalse(linkFormRedis); + } else { + shortLink = await Link.getLink(linkID); + + await RedisProvider.getClient().set(linkID, JSON.stringify(shortLink)); + } + + return shortLink; + } + + private static async its404(c: Context) { + return c.html(await new Response(Bun.file(LinkAPI.path + "404.html")).text(), 404); + } } \ No newline at end of file diff --git a/apps/linkos/src/services/GetLink.ts b/apps/linkos/src/services/GetLink.ts index c3aa4bf..57f877e 100644 --- a/apps/linkos/src/services/GetLink.ts +++ b/apps/linkos/src/services/GetLink.ts @@ -10,6 +10,7 @@ export default class GetLink { app.get('/', LinkAPI.getPublic); app.get('/:link', LinkAPI.get); app.get('/qr/:link', LinkAPI.getQr); + app.post('/password/:link', LinkAPI.getWithPassword); Log.info('Starting serving Linkos getlink endpoint') return app;