✨ Add vanity ID creation feature
parent
c8d762e6b4
commit
c0bfe77104
93
mod.js
93
mod.js
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
Reference in New Issue