Add vanity ID creation feature

dev
KaKi87 2022-03-05 19:10:45 +01:00
parent c8d762e6b4
commit c0bfe77104
2 changed files with 78 additions and 17 deletions

93
mod.js
View File

@ -57,52 +57,97 @@ createRoute({
{
let idSize;
createRoute({
method: 'POST',
path: '/',
schema: createSchema,
handler: async (
const
schema = createSchema,
handler = async (
request,
h,
{
username,
password,
path,
params,
body,
response
}
) => {
if(!idSize)
idSize = await getSetting('idSize');
let id = nanoid({ size: idSize });
if((await db.queryArray('SELECT 1 FROM "url" WHERE "id" = $1', [id])).rows[0]?.[0] === 1){
idSize += 1;
let id, urlExists;
if(username){
let codeExists, urlEditionCode;
([
{ rows: [[codeExists] = []] },
{ rows: [[urlExists, urlEditionCode] = []] }
] = await Promise.all([
db.queryArray('SELECT 1 FROM "vanityCode" WHERE "code" = $1', [username]),
db.queryArray('SELECT 1, "editionCode" FROM "url" WHERE "id" = $1', [path.id])
]));
if(codeExists){
if(urlExists){
response.code(409);
return response;
}
else {
await db.queryArray('DELETE FROM "vanityCode" WHERE "code" = $1', [username]);
id = path.id;
}
}
else {
if(urlExists){
if(verify(username, urlEditionCode))
id = path.id;
else {
response.code(401);
return response;
}
}
else {
response.code(401);
return response;
}
}
}
else {
if(!idSize)
idSize = await getSetting('idSize');
id = nanoid({ size: idSize });
await setSetting({ idSize });
if((await db.queryArray('SELECT 1 FROM "url" WHERE "id" = $1', [id])).rows[0]?.[0] === 1){
idSize += 1;
id = nanoid({ size: idSize });
await setSetting({ idSize });
}
}
const
creationTimestamp = Date.now(),
deletionCode = params.isDeletable ? nanoid({ size: 30 }) : undefined;
timestamp = Date.now(),
deletionCode = params.isDeletable && !urlExists ? nanoid({ size: 30 }) : undefined;
await db.queryArray(`
INSERT INTO "url" (
"id",
"creationTimestamp",
"${password ? 'encryptedConfig' : 'config'}"
${path.id ? ', "editionCode"' : ''}
${deletionCode ? ', "deletionCode"' : ''}
${body.webhook ? ', "webhookSecretConfig"' : ''}
)
VALUES (
$id,
$creationTimestamp,
$timestamp,
$${password ? 'encryptedConfig' : 'config'}
${path.id ? ', $editionCode' : ''}
${deletionCode ? ', $deletionCode' : ''}
${body.webhook ? ', $webhookSecretConfig' : ''}
)
ON CONFLICT ("id") DO UPDATE SET
"editionTimestamp" = $timestamp,
"config" = ${password ? 'null' : '$config'},
"encryptedConfig" = ${password ? '$encryptedConfig' : 'null'}
${body.webhook ? ', "webhookSecretConfig" = $webhookSecretConfig' : ''}
`, {
id,
creationTimestamp,
timestamp,
...password
? { encryptedConfig: await new Cryptr(password).encrypt(JSON.stringify(body)) }
: { config: body },
...path.id ? { editionCode: hash(username) } : {},
...deletionCode ? { deletionCode: hash(deletionCode) } : {},
...body.webhook ? {
webhookSecretConfig: {
@ -114,11 +159,22 @@ createRoute({
});
response.body = {
id,
creationTimestamp,
[urlExists ? 'editionTimestamp' : 'creationTimestamp']: timestamp,
deletionCode
};
return response;
}
};
createRoute({
method: 'POST',
path: '/',
schema,
handler
});
createRoute({
method: 'PUT',
path: '/{id}',
schema,
handler
});
}
@ -353,6 +409,7 @@ createRoute({
const {
rows: [[
creationTimestamp,
editionTimestamp,
config,
encryptedConfig,
deletionTimestamp,
@ -361,6 +418,7 @@ createRoute({
} = await db.queryArray(`
SELECT
"creationTimestamp",
"editionTimestamp",
"config",
"encryptedConfig" ${password ? '' : 'IS NOT null'},
"deletionTimestamp",
@ -377,6 +435,7 @@ createRoute({
}
if(creationTimestamp) response.body = {
creationTimestamp: Number(creationTimestamp),
editionTimestamp: Number(editionTimestamp),
config: decryptedConfig || config,
isEncrypted: !!encryptedConfig,
deletionTimestamp: deletionTimestamp && Number(deletionTimestamp),

View File

@ -3,6 +3,8 @@ CREATE TABLE "url" (
"creationTimestamp" BIGINT NOT NULL,
"config" JSON,
"encryptedConfig" TEXT,
"editionCode" VARCHAR(60),
"editionTimestamp" BIGINT,
"deletionCode" VARCHAR(60),
"deletionTimestamp" BIGINT,
"deletionMessage" VARCHAR(255),