feat(share, config): more variables, placeholder and reset default (#132)

* More email share vars + unfinished placeolders config

{desc} {expires} vars
(unfinished) config placeholder vals

* done

* migrate

* edit seed

* removed comments

* refactor: replace dependecy `luxon` with `moment`

* update shareRecipientsMessage message

* chore: remove `luxon`

* fix: grammatically incorrect `shareRecipientsMessage` message

* changed to defaultValue and value instead

* fix: don't expose defaultValue to non admin user

* fix: update default value if default value changes

* refactor: set config value to null instead of a empty string

* refactor: merge two migrations into one

* fix value check empty

---------

Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
iUnstable0
2023-03-23 14:31:21 +07:00
committed by GitHub
parent a0d1d98e24
commit beece56327
12 changed files with 149 additions and 73 deletions

View File

@@ -21,10 +21,12 @@ export class ConfigService {
if (!configVariable) throw new Error(`Config variable ${key} not found`);
if (configVariable.type == "number") return parseInt(configVariable.value);
if (configVariable.type == "boolean") return configVariable.value == "true";
const value = configVariable.value ?? configVariable.defaultValue;
if (configVariable.type == "number") return parseInt(value);
if (configVariable.type == "boolean") return value == "true";
if (configVariable.type == "string" || configVariable.type == "text")
return configVariable.value;
return value;
}
async getByCategory(category: string) {
@@ -35,8 +37,9 @@ export class ConfigService {
return configVariables.map((variable) => {
return {
key: `${variable.category}.${variable.name}`,
...variable,
key: `${variable.category}.${variable.name}`,
value: variable.value ?? variable.defaultValue,
};
});
}
@@ -48,8 +51,9 @@ export class ConfigService {
return configVariables.map((variable) => {
return {
key: `${variable.category}.${variable.name}`,
...variable,
key: `${variable.category}.${variable.name}`,
value: variable.value ?? variable.defaultValue,
};
});
}
@@ -77,7 +81,9 @@ export class ConfigService {
if (!configVariable || configVariable.locked)
throw new NotFoundException("Config variable not found");
if (
if (value == "") {
value = null;
} else if (
typeof value != configVariable.type &&
typeof value == "string" &&
configVariable.type != "text"
@@ -94,7 +100,7 @@ export class ConfigService {
name: key.split(".")[1],
},
},
data: { value: value.toString() },
data: { value: value ? value.toString() : null },
});
this.configVariables = await this.prisma.config.findMany();

View File

@@ -8,6 +8,9 @@ export class AdminConfigDTO extends ConfigDTO {
@Expose()
secret: boolean;
@Expose()
defaultValue: string;
@Expose()
updatedAt: Date;

View File

@@ -1,11 +1,10 @@
import { IsNotEmpty, IsString, ValidateIf } from "class-validator";
import { IsNotEmpty, IsString } from "class-validator";
class UpdateConfigDTO {
@IsString()
key: string;
@IsNotEmpty()
@ValidateIf((dto) => dto.value !== "")
value: string | number | boolean;
}

View File

@@ -4,6 +4,7 @@ import {
Logger,
} from "@nestjs/common";
import { User } from "@prisma/client";
import * as moment from "moment";
import * as nodemailer from "nodemailer";
import { ConfigService } from "src/config/config.service";
@@ -43,10 +44,12 @@ export class EmailService {
});
}
async sendMailToShareRecepients(
async sendMailToShareRecipients(
recipientEmail: string,
shareId: string,
creator?: User
creator?: User,
description?: string,
expiration?: Date
) {
if (!this.config.get("email.enableShareEmailRecipients"))
throw new InternalServerErrorException("Email service disabled");
@@ -61,6 +64,13 @@ export class EmailService {
.replaceAll("\\n", "\n")
.replaceAll("{creator}", creator?.username ?? "Someone")
.replaceAll("{shareUrl}", shareUrl)
.replaceAll("{desc}", description ?? "No description")
.replaceAll(
"{expires}",
moment(expiration).unix() != 0
? moment(expiration).fromNow()
: "in: never"
)
);
}

View File

@@ -142,12 +142,14 @@ export class ShareService {
this.prisma.share.update({ where: { id }, data: { isZipReady: true } })
);
// Send email for each recepient
for (const recepient of share.recipients) {
await this.emailService.sendMailToShareRecepients(
recepient.email,
// Send email for each recipient
for (const recipient of share.recipients) {
await this.emailService.sendMailToShareRecipients(
recipient.email,
share.id,
share.creator
share.creator,
share.description,
share.expiration
);
}
@@ -163,7 +165,7 @@ export class ShareService {
}
// Check if any file is malicious with ClamAV
this.clamScanService.checkAndRemove(share.id);
void this.clamScanService.checkAndRemove(share.id);
if (share.reverseShare) {
await this.prisma.reverseShare.update({
@@ -172,7 +174,7 @@ export class ShareService {
});
}
return await this.prisma.share.update({
return this.prisma.share.update({
where: { id },
data: { uploadLocked: true },
});
@@ -195,14 +197,12 @@ export class ShareService {
include: { recipients: true },
});
const sharesWithEmailRecipients = shares.map((share) => {
return shares.map((share) => {
return {
...share,
recipients: share.recipients.map((recipients) => recipients.email),
};
});
return sharesWithEmailRecipients;
}
async get(id: string): Promise<any> {
@@ -222,7 +222,7 @@ export class ShareService {
throw new NotFoundException("Share not found");
return {
...share,
hasPassword: share.security?.password ? true : false,
hasPassword: !!share.security?.password,
};
}