feat: reverse shares (#86)

* add first concept

* add reverse share funcionality to frontend

* allow creator to limit share expiration

* moved reverse share in seperate module

* add table to manage reverse shares

* delete complete share if reverse share was deleted

* optimize function names

* add db migration

* enable reverse share email notifications

* fix config variable descriptions

* fix migration for new installations
This commit is contained in:
Elias Schneider
2023-01-26 13:44:04 +01:00
committed by GitHub
parent 1ceb07b89e
commit 4a5fb549c6
43 changed files with 1456 additions and 280 deletions

View File

@@ -0,0 +1,91 @@
/*
Warnings:
- The primary key for the `Config` table will be changed. If it partially fails, the table could be left without primary key constraint.
- Added the required column `id` to the `Config` table without a default value. This is not possible if the table is not empty.
*/
-- CreateTable
CREATE TABLE "ReverseShare" (
"id" TEXT NOT NULL PRIMARY KEY,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"token" TEXT NOT NULL,
"shareExpiration" DATETIME NOT NULL,
"maxShareSize" TEXT NOT NULL,
"sendEmailNotification" BOOLEAN NOT NULL,
"used" BOOLEAN NOT NULL DEFAULT false,
"creatorId" TEXT NOT NULL,
"shareId" TEXT,
CONSTRAINT "ReverseShare_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "ReverseShare_shareId_fkey" FOREIGN KEY ("shareId") REFERENCES "Share" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Config" (
"id" INTEGER,
"updatedAt" DATETIME NOT NULL,
"key" TEXT NOT NULL,
"type" TEXT NOT NULL,
"value" TEXT NOT NULL,
"description" TEXT NOT NULL,
"category" TEXT NOT NULL,
"obscured" BOOLEAN NOT NULL DEFAULT false,
"secret" BOOLEAN NOT NULL DEFAULT true,
"locked" BOOLEAN NOT NULL DEFAULT false
);
INSERT INTO "new_Config" ("category", "description", "key", "locked", "obscured", "secret", "type", "updatedAt", "value") SELECT "category", "description", "key", "locked", "obscured", "secret", "type", "updatedAt", "value" FROM "Config";
DROP TABLE "Config";
ALTER TABLE "new_Config" RENAME TO "Config";
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
-- CreateIndex
CREATE UNIQUE INDEX "ReverseShare_token_key" ON "ReverseShare"("token");
-- CreateIndex
CREATE UNIQUE INDEX "ReverseShare_shareId_key" ON "ReverseShare"("shareId");
-- Add ids to existing settings
UPDATE Config SET id = 1 WHERE key = "SETUP_FINISHED";
UPDATE Config SET id = 2 WHERE key = "APP_URL";
UPDATE Config SET id = 3 WHERE key = "SHOW_HOME_PAGE";
UPDATE Config SET id = 4 WHERE key = "ALLOW_REGISTRATION";
UPDATE Config SET id = 5 WHERE key = "ALLOW_UNAUTHENTICATED_SHARES";
UPDATE Config SET id = 6 WHERE key = "MAX_SHARE_SIZE";
UPDATE Config SET id = 7 WHERE key = "JWT_SECRET";
UPDATE Config SET id = 8 WHERE key = "TOTP_SECRET";
UPDATE Config SET id = 9, key = "ENABLE_SHARE_EMAIL_RECIPIENTS" WHERE key = "ENABLE_EMAIL_RECIPIENTS";
UPDATE Config SET id = 10, key = "SHARE_RECEPIENTS_EMAIL_MESSAGE" WHERE key = "EMAIL_MESSAGE";
UPDATE Config SET id = 11, key = "SHARE_RECEPIENTS_EMAIL_SUBJECT" WHERE key = "EMAIL_SUBJECT";
UPDATE Config SET id = 15 WHERE key = "SMTP_HOST";
UPDATE Config SET id = 16 WHERE key = "SMTP_PORT";
UPDATE Config SET id = 17 WHERE key = "SMTP_EMAIL";
UPDATE Config SET id = 18 WHERE key = "SMTP_USERNAME";
UPDATE Config SET id = 19 WHERE key = "SMTP_PASSWORD";
INSERT INTO Config (`id`, `key`, `description`, `type`, `value`, `category`, `secret`, `updatedAt`) VALUES (14, "SMTP_ENABLED", "Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.", "boolean", IFNULL((SELECT value FROM Config WHERE key="ENABLE_SHARE_EMAIL_RECIPIENTS"), "false"), "smtp", 0, strftime('%s', 'now'));
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Config" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"updatedAt" DATETIME NOT NULL,
"key" TEXT NOT NULL,
"type" TEXT NOT NULL,
"value" TEXT NOT NULL,
"description" TEXT NOT NULL,
"category" TEXT NOT NULL,
"obscured" BOOLEAN NOT NULL DEFAULT false,
"secret" BOOLEAN NOT NULL DEFAULT true,
"locked" BOOLEAN NOT NULL DEFAULT false
);
INSERT INTO "new_Config" ("id", "category", "description", "key", "locked", "obscured", "secret", "type", "updatedAt", "value") SELECT "id", "category", "description", "key", "locked", "obscured", "secret", "type", "updatedAt", "value" FROM "Config";
DROP TABLE "Config";
ALTER TABLE "new_Config" RENAME TO "Config";
DELETE from Config WHERE key="MAX_FILE_SIZE";
CREATE UNIQUE INDEX "Config_key_key" ON "Config"("key");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View File

@@ -20,6 +20,7 @@ model User {
shares Share[]
refreshTokens RefreshToken[]
loginTokens LoginToken[]
reverseShares ReverseShare[]
totpEnabled Boolean @default(false)
totpVerified Boolean @default(false)
@@ -59,13 +60,33 @@ model Share {
description String?
removedReason String?
creatorId String?
creator User? @relation(fields: [creatorId], references: [id], onDelete: Cascade)
creatorId String?
creator User? @relation(fields: [creatorId], references: [id], onDelete: Cascade)
reverseShare ReverseShare?
security ShareSecurity?
recipients ShareRecipient[]
files File[]
}
model ReverseShare {
id String @id @default(uuid())
createdAt DateTime @default(now())
token String @unique @default(uuid())
shareExpiration DateTime
maxShareSize String
sendEmailNotification Boolean
used Boolean @default(false)
creatorId String
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
shareId String? @unique
share Share? @relation(fields: [shareId], references: [id], onDelete: Cascade)
}
model ShareRecipient {
id String @id @default(uuid())
email String
@@ -97,9 +118,10 @@ model ShareSecurity {
}
model Config {
id Int @id
updatedAt DateTime @updatedAt
key String @id
key String @unique
type String
value String
description String

View File

@@ -3,6 +3,7 @@ import * as crypto from "crypto";
const configVariables: Prisma.ConfigCreateInput[] = [
{
id: 1,
key: "SETUP_FINISHED",
description: "Whether the setup has been finished",
type: "boolean",
@@ -12,6 +13,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
locked: true,
},
{
id: 2,
key: "APP_URL",
description: "On which URL Pingvin Share is available",
type: "string",
@@ -20,6 +22,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
secret: false,
},
{
id: 3,
key: "SHOW_HOME_PAGE",
description: "Whether to show the home page",
type: "boolean",
@@ -28,6 +31,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
secret: false,
},
{
id: 4,
key: "ALLOW_REGISTRATION",
description: "Whether registration is allowed",
type: "boolean",
@@ -36,6 +40,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
secret: false,
},
{
id: 5,
key: "ALLOW_UNAUTHENTICATED_SHARES",
description: "Whether unauthorized users can create shares",
type: "boolean",
@@ -44,6 +49,8 @@ const configVariables: Prisma.ConfigCreateInput[] = [
secret: false,
},
{
id: 6,
key: "MAX_SHARE_SIZE",
description: "Maximum share size in bytes",
type: "number",
@@ -52,6 +59,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
secret: false,
},
{
id: 7,
key: "JWT_SECRET",
description: "Long random string used to sign JWT tokens",
type: "string",
@@ -60,6 +68,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
locked: true,
},
{
id: 8,
key: "TOTP_SECRET",
description: "A 16 byte random string used to generate TOTP secrets",
type: "string",
@@ -68,65 +77,103 @@ const configVariables: Prisma.ConfigCreateInput[] = [
locked: true,
},
{
key: "ENABLE_EMAIL_RECIPIENTS",
id: 9,
key: "ENABLE_SHARE_EMAIL_RECIPIENTS",
description:
"Whether to send emails to recipients. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
"Whether to allow emails to share recipients. Only enable this if you have enabled SMTP.",
type: "boolean",
value: "false",
category: "email",
secret: false,
},
{
key: "EMAIL_MESSAGE",
id: 10,
key: "SHARE_RECEPIENTS_EMAIL_MESSAGE",
description:
"Message which gets sent to the recipients. {creator} and {shareUrl} will be replaced with the creator's name and the share URL.",
"Message which gets sent to the share recipients. {creator} and {shareUrl} will be replaced with the creator's name and the share URL.",
type: "text",
value:
"Hey!\n{creator} shared some files with you. View or download the files with this link: {shareUrl}\nShared securely with Pingvin Share 🐧",
category: "email",
category: "email",
},
{
key: "EMAIL_SUBJECT",
description: "Subject of the email which gets sent to the recipients.",
id: 11,
key: "SHARE_RECEPIENTS_EMAIL_SUBJECT",
description:
"Subject of the email which gets sent to the share recipients.",
type: "string",
value: "Files shared with you",
category: "email",
},
{
id: 12,
key: "REVERSE_SHARE_EMAIL_MESSAGE",
description:
"Message which gets sent when someone created a share with your reverse share link. {shareUrl} will be replaced with the creator's name and the share URL.",
type: "text",
value:
"Hey!\nA share was just created with your reverse share link: {shareUrl}\nShared securely with Pingvin Share 🐧",
category: "email",
},
{
id: 13,
key: "REVERSE_SHARE_EMAIL_SUBJECT",
description:
"Subject of the email which gets sent when someone created a share with your reverse share link.",
type: "string",
value: "Reverse share link used",
category: "email",
},
{
id: 14,
key: "SMTP_ENABLED",
description:
"Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
type: "boolean",
value: "false",
category: "smtp",
secret: false,
},
{
id: 15,
key: "SMTP_HOST",
description: "Host of the SMTP server",
type: "string",
value: "",
category: "email",
category: "smtp",
},
{
id: 16,
key: "SMTP_PORT",
description: "Port of the SMTP server",
type: "number",
value: "0",
category: "email",
category: "smtp",
},
{
id: 17,
key: "SMTP_EMAIL",
description: "Email address which the emails get sent from",
type: "string",
value: "",
category: "email",
category: "smtp",
},
{
id: 18,
key: "SMTP_USERNAME",
description: "Username of the SMTP server",
type: "string",
value: "",
category: "email",
category: "smtp",
},
{
id: 19,
key: "SMTP_PASSWORD",
description: "Password of the SMTP server",
type: "string",
value: "",
obscured: true,
category: "email",
category: "smtp",
},
];