Compare commits

...

16 Commits
0.5.1 ... 0.6.0

Author SHA1 Message Date
Nicolai Ort 3803ac9197 🚀RELEASE 0.6.0
continuous-integration/drone/push Build is passing Details
2021-09-25 18:03:09 +02:00
Nicolai Ort e1621b72ad
Added rudementary page content
continuous-integration/drone/push Build is passing Details
2021-09-25 17:44:34 +02:00
Nicolai Ort b64a8436e7
Updated opengraph type
ref #2
2021-09-25 17:42:44 +02:00
Nicolai Ort d8ed9a149f
Switched docker base images to odit mirror 2021-09-25 17:38:11 +02:00
Nicolai Ort 9d7125a311
Now with custom opengraph (tm)
continuous-integration/drone/push Build is passing Details
ref #2
2021-09-25 17:35:52 +02:00
Nicolai Ort 6d71a3ebf4
Removed unused log
continuous-integration/drone/push Build is passing Details
2021-09-25 17:27:59 +02:00
Nicolai Ort 75adbf73cf
Now with working bad bot detection
ref #2
2021-09-25 17:27:41 +02:00
Nicolai Ort e5b8557e4c
Getters now return the no_preview status 2021-09-25 17:21:30 +02:00
Nicolai Ort 33d7c94648
New urls can now be created with disabled preview
ref #2
2021-09-25 17:19:36 +02:00
Nicolai Ort f6b2ae523d
Added bot check for native short urls
ref #2
2021-09-25 17:17:42 +02:00
Nicolai Ort 0a500f16cd
Added migration for disallowing bot previews 2021-09-25 17:16:38 +02:00
Nicolai Ort 61da5d8110
Added basic bot checking 2021-09-25 17:14:34 +02:00
Nicolai Ort 773b286216
Added package for bot recognition 2021-09-25 17:12:52 +02:00
Nicolai Ort d097eccbd9
removed logging 2021-09-25 17:12:22 +02:00
Nicolai Ort f15282a3f9
Log user agents
continuous-integration/drone/push Build is passing Details
2021-09-25 17:09:19 +02:00
Nicolai Ort 0a8945a294
Added noindex header to all shorturl routes
continuous-integration/drone/push Build is passing Details
ref #2
2021-09-25 16:59:28 +02:00
6 changed files with 87 additions and 13 deletions

View File

@ -2,8 +2,29 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.6.0](https://git.odit.services/kauft.es/linkylinky/compare/0.5.1...0.6.0)
- Now with custom opengraph (tm) [`9d7125a`](https://git.odit.services/kauft.es/linkylinky/commit/9d7125a31186f3b7f33df4875db12c67cf91f536)
- Added rudementary page content [`e1621b7`](https://git.odit.services/kauft.es/linkylinky/commit/e1621b72ade1fce381f30bcf310a6dcf8d1c65ea)
- Added migration for disallowing bot previews [`0a500f1`](https://git.odit.services/kauft.es/linkylinky/commit/0a500f16cde0b0e38a115dd4e76185a2a45dda49)
- Added basic bot checking [`61da5d8`](https://git.odit.services/kauft.es/linkylinky/commit/61da5d81108a4b86f92e1c05ca99372c6b188347)
- Now with working bad bot detection [`75adbf7`](https://git.odit.services/kauft.es/linkylinky/commit/75adbf73cfbf4fadf2cd632ecb687eff95749f52)
- New urls can now be created with disabled preview [`33d7c94`](https://git.odit.services/kauft.es/linkylinky/commit/33d7c94648d062ece3fa437e71ce1ded70324cd8)
- Added bot check for native short urls [`f6b2ae5`](https://git.odit.services/kauft.es/linkylinky/commit/f6b2ae523da149b72f2be6d9171584cdc0be6e99)
- Added package for bot recognition [`773b286`](https://git.odit.services/kauft.es/linkylinky/commit/773b286216c9e530ccdf3fbfcfe95fa938097be5)
- Getters now return the no_preview status [`e5b8557`](https://git.odit.services/kauft.es/linkylinky/commit/e5b8557e4ccae90981e675c2adae81236aa9144e)
- Added noindex header to all shorturl routes [`0a8945a`](https://git.odit.services/kauft.es/linkylinky/commit/0a8945a294de2bc5bce9410f3ebf20b8f5abd0a5)
- Switched docker base images to odit mirror [`d8ed9a1`](https://git.odit.services/kauft.es/linkylinky/commit/d8ed9a149fddae8e8cc61b78cbc940a9d7ade8f2)
- Updated opengraph type [`b64a843`](https://git.odit.services/kauft.es/linkylinky/commit/b64a8436e745d176cc49ef72434dce0f8f1bcc12)
- Log user agents [`f15282a`](https://git.odit.services/kauft.es/linkylinky/commit/f15282a3f9bdaaf09a36d8662b64a5bc2740633f)
- Removed unused log [`6d71a3e`](https://git.odit.services/kauft.es/linkylinky/commit/6d71a3ebf4d880b8291cacd620f86416cff0d744)
- removed logging [`d097ecc`](https://git.odit.services/kauft.es/linkylinky/commit/d097eccbd925e3627fa710d7891d269b372d174c)
#### [0.5.1](https://git.odit.services/kauft.es/linkylinky/compare/0.5.0...0.5.1) #### [0.5.1](https://git.odit.services/kauft.es/linkylinky/compare/0.5.0...0.5.1)
> 21 August 2021
- 🚀RELEASE 0.5.1 [`b871e42`](https://git.odit.services/kauft.es/linkylinky/commit/b871e4295dc4b067f4f4dd28c3f940c8aa9624e0)
- Added endpoint to query over all visited urls [`bb99c2d`](https://git.odit.services/kauft.es/linkylinky/commit/bb99c2dcd1ce89af1bc27a035be5265345d2a05f) - Added endpoint to query over all visited urls [`bb99c2d`](https://git.odit.services/kauft.es/linkylinky/commit/bb99c2dcd1ce89af1bc27a035be5265345d2a05f)
- Added optional filtering by provider [`0945060`](https://git.odit.services/kauft.es/linkylinky/commit/0945060a49ed35c038df2c04bbd07174bc5654ca) - Added optional filtering by provider [`0945060`](https://git.odit.services/kauft.es/linkylinky/commit/0945060a49ed35c038df2c04bbd07174bc5654ca)
- Shortened return to avoid variable memory asignment [`f7eae96`](https://git.odit.services/kauft.es/linkylinky/commit/f7eae96b8c3479d333fc00bc36bce451733700db) - Shortened return to avoid variable memory asignment [`f7eae96`](https://git.odit.services/kauft.es/linkylinky/commit/f7eae96b8c3479d333fc00bc36bce451733700db)

View File

@ -1,4 +1,4 @@
FROM node:16.6.2-alpine3.14 FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14
WORKDIR /app WORKDIR /app
COPY package.json . COPY package.json .
COPY yarn.lock . COPY yarn.lock .
@ -9,7 +9,7 @@ COPY knexfile.js ./
RUN mkdir db RUN mkdir db
# #
# FROM astefanutti/scratch-node:16.0.0 # FROM astefanutti/scratch-node:16.0.0
FROM node:16.6.2-alpine3.14 FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14
WORKDIR /app WORKDIR /app
COPY --from=0 /app /app COPY --from=0 /app /app
ENV NODE_ENV production ENV NODE_ENV production

View File

@ -0,0 +1,10 @@
exports.up = function(knex) {
return knex.schema.table('urls', function (table) {
table.boolean('no_preview').defaultTo(false);
});
};
exports.down = function(knex) {
};

View File

@ -1,6 +1,6 @@
{ {
"name": "@odit/shortener-backend", "name": "@odit/shortener-backend",
"version": "0.5.1", "version": "0.6.0",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
"private": false, "private": false,
@ -31,6 +31,7 @@
"fastify-basic-auth": "^2.1.0", "fastify-basic-auth": "^2.1.0",
"fastify-cors": "^6.0.2", "fastify-cors": "^6.0.2",
"fastify-jwt": "^3.0.1", "fastify-jwt": "^3.0.1",
"isbot": "^3.3.3",
"knex": "^0.21.21", "knex": "^0.21.21",
"sqlite3": "^5.0.2", "sqlite3": "^5.0.2",
"uniqid": "^5.3.0" "uniqid": "^5.3.0"

View File

@ -2,6 +2,7 @@ const fastify = require('fastify')({ logger: true })
var uniqid = require('uniqid'); var uniqid = require('uniqid');
require('dotenv').config(); require('dotenv').config();
const argon2 = require('argon2'); const argon2 = require('argon2');
const isBot = require('isbot')
let config = { let config = {
domain: process.env.DOMAIN || "localhost:3000", domain: process.env.DOMAIN || "localhost:3000",
@ -103,13 +104,44 @@ fastify.get('/:shortcode', async (req, res) => {
if (!shortcode) { if (!shortcode) {
return 404; return 404;
} }
const target = await knex.select('target') const target = await knex.select('target', 'no_preview')
.from('urls') .from('urls')
.where('shortcode', '=', shortcode) .where('shortcode', '=', shortcode)
.limit(1); .limit(1);
if (!target[0]) { if (!target[0]) {
return 404 return 404
} }
if (isBot(req.headers['user-agent']) && target[0].no_preview) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="og:title" content="LinkyLinky">
<meta property="og:site_name" content="LinkyLinky by Kauft.es">
<meta property="og:url" content="https://kauft.es/">
<meta property="og:description" content="LinkyLinky by Kauft.es is a custom url shortener. You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders.">
<meta property="og:type" content="article">
<meta property="og:image" content="https://kauft.es/dashboard/icon_128.png">
<title>LinkyLinky</title>
</head>
<body>
<p align="center">
<img height="150" src="https://kauft.es/dashboard/icon_128.png">
<h1 align="center">LinkyLinky 🔗</h1>
<h3 align="center">A small url shortener, originaly developed for kauft.es</h3>
<p>LinkyLinky by Kauft.es is a custom url shortener.<br>
You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders.</p>
</p>
</body>
</html>
`;
}
res.redirect(302, target[0].target); res.redirect(302, target[0].target);
await knex('visits').insert({ shortcode, provider: 'native' }); await knex('visits').insert({ shortcode, provider: 'native' });
}) })
@ -121,6 +153,7 @@ const newUrlSchema = {
properties: { properties: {
target: { type: 'string' }, target: { type: 'string' },
shortcode: { type: 'string' }, shortcode: { type: 'string' },
no_preview: { type: 'boolean' },
} }
} }
}; };
@ -129,6 +162,7 @@ const newUrlSchema = {
fastify.post('/api', { newUrlSchema }, async (req, res) => { fastify.post('/api', { newUrlSchema }, async (req, res) => {
const target = req.body?.target; const target = req.body?.target;
let shortcode = req.body?.shortcode; let shortcode = req.body?.shortcode;
let no_preview = req.body?.no_preview || false;
//Check if the user provided a target //Check if the user provided a target
if (!target) { if (!target) {
@ -148,7 +182,7 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
return response; return response;
} }
} }
const exists = await knex.select('shortcode') const exists = await knex.select('shortcode', 'no_preview')
.from('urls') .from('urls')
.where('target', '=', target) .where('target', '=', target)
.limit(1); .limit(1);
@ -157,7 +191,8 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
return { return {
url: `${config.getBaseUrl()}/${shortcode}`, url: `${config.getBaseUrl()}/${shortcode}`,
shortcode, shortcode,
target target,
no_preview: exists[0].no_preview
} }
} }
shortcode = uniqid(); shortcode = uniqid();
@ -179,12 +214,13 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
} }
//Create a new db entry //Create a new db entry
await knex('urls').insert({ target, shortcode }); await knex('urls').insert({ target, shortcode, no_preview });
return { return {
url: `${config.getBaseUrl()}/${shortcode}`, url: `${config.getBaseUrl()}/${shortcode}`,
shortcode, shortcode,
target target,
no_preview
} }
}); });
@ -211,7 +247,7 @@ fastify.get('/api/:shortcode', async (req, res) => {
return 404; return 404;
} }
const exists = await knex.select('shortcode', 'target') const exists = await knex.select('shortcode', 'target', 'no_preview')
.from('urls') .from('urls')
.where('shortcode', '=', shortcode) .where('shortcode', '=', shortcode)
.limit(1); .limit(1);
@ -227,6 +263,7 @@ fastify.get('/api/:shortcode', async (req, res) => {
url: `${config.getBaseUrl()}/${exists[0].shortcode}`, url: `${config.getBaseUrl()}/${exists[0].shortcode}`,
shortcode: exists[0].shortcode, shortcode: exists[0].shortcode,
target: exists[0].target, target: exists[0].target,
no_preview: exists[0].no_preview,
visits: visits.length visits: visits.length
} }
}); });
@ -285,10 +322,10 @@ fastify.after(() => {
//Get all visits api route //Get all visits api route
fastify.get('/api/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { fastify.get('/api/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
if(req.query.provider){ if (req.query.provider) {
return await knex.select('shortcode', 'provider', 'timestamp') return await knex.select('shortcode', 'provider', 'timestamp')
.from('visits') .from('visits')
.where("provider", "=", req.query.provider); .where("provider", "=", req.query.provider);
} }
return await knex.select('shortcode', 'provider', 'timestamp') return await knex.select('shortcode', 'provider', 'timestamp')
.from('visits'); .from('visits');
@ -313,7 +350,7 @@ fastify.after(() => {
//Get all urls api route //Get all urls api route
fastify.get('/api', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => { fastify.get('/api', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
urls = await knex.select('target', 'shortcode') urls = await knex.select('target', 'shortcode', 'no_preview')
.from('urls'); .from('urls');
for (let url of urls) { for (let url of urls) {

View File

@ -2228,6 +2228,11 @@ isarray@1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isbot@^3.3.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.3.3.tgz#6a2124a6c1dda5db2d0060c4e292b346ecbd2249"
integrity sha512-a3HFPPsvtLroqpuTHHJTaUpPHUO0vjPbptJDzJYkymRvOI8tugWM6zE2oq22w5VOq4A5hrX+YRS7VdIPAgWLfw==
isexe@^2.0.0: isexe@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"