Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f9f8b6fe7 | ||
|
|
bf1b2633c8 | ||
|
|
b3ea96c191 |
@@ -1,3 +1,10 @@
|
|||||||
|
## [1.8.1](https://github.com/stonith404/pingvin-share/compare/v1.8.0...v1.8.1) (2025-01-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* wrong validation for expiration in reverse share modal ([b3ea96c](https://github.com/stonith404/pingvin-share/commit/b3ea96c1916980863fc6903c64cd2a7b32d66cfb))
|
||||||
|
|
||||||
## [1.8.0](https://github.com/stonith404/pingvin-share/compare/v1.7.2...v1.8.0) (2025-01-02)
|
## [1.8.0](https://github.com/stonith404/pingvin-share/compare/v1.7.2...v1.8.0) (2025-01-02)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
backend/package-lock.json
generated
4
backend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-backend",
|
"name": "pingvin-share-backend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pingvin-share-backend",
|
"name": "pingvin-share-backend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.679.0",
|
"@aws-sdk/client-s3": "^3.679.0",
|
||||||
"@nestjs/cache-manager": "^2.2.2",
|
"@nestjs/cache-manager": "^2.2.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-backend",
|
"name": "pingvin-share-backend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nest build",
|
"build": "nest build",
|
||||||
"dev": "cross-env NODE_ENV=development nest start --watch",
|
"dev": "cross-env NODE_ENV=development nest start --watch",
|
||||||
|
|||||||
@@ -345,7 +345,9 @@ export class AuthService {
|
|||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
const now = moment();
|
const now = moment();
|
||||||
const sessionDuration = this.config.get("general.sessionDuration");
|
const sessionDuration = this.config.get("general.sessionDuration");
|
||||||
const maxAge = moment(now).add(sessionDuration.value, sessionDuration.unit).diff(now);
|
const maxAge = moment(now)
|
||||||
|
.add(sessionDuration.value, sessionDuration.unit)
|
||||||
|
.diff(now);
|
||||||
response.cookie("refresh_token", refreshToken, {
|
response.cookie("refresh_token", refreshToken, {
|
||||||
path: "/api/auth/token",
|
path: "/api/auth/token",
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ export class ConfigService extends EventEmitter {
|
|||||||
if (configVariable.type == "boolean") return value == "true";
|
if (configVariable.type == "boolean") return value == "true";
|
||||||
if (configVariable.type == "string" || configVariable.type == "text")
|
if (configVariable.type == "string" || configVariable.type == "text")
|
||||||
return value;
|
return value;
|
||||||
if (configVariable.type == "timespan")
|
if (configVariable.type == "timespan") return stringToTimespan(value);
|
||||||
return stringToTimespan(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByCategory(category: string) {
|
async getByCategory(category: string) {
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ export class ReverseShareService {
|
|||||||
.toDate();
|
.toDate();
|
||||||
|
|
||||||
const parsedExpiration = parseRelativeDateToAbsolute(data.shareExpiration);
|
const parsedExpiration = parseRelativeDateToAbsolute(data.shareExpiration);
|
||||||
|
const maxExpiration = this.config.get("share.maxExpiration");
|
||||||
if (
|
if (
|
||||||
this.config.get("share.maxExpiration") !== 0 &&
|
maxExpiration.value !== 0 &&
|
||||||
parsedExpiration >
|
parsedExpiration >
|
||||||
moment().add(this.config.get("share.maxExpiration"), "hours").toDate()
|
moment().add(maxExpiration.value, maxExpiration.unit).toDate()
|
||||||
) {
|
) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
"Expiration date exceeds maximum expiration date",
|
"Expiration date exceeds maximum expiration date",
|
||||||
|
|||||||
@@ -61,9 +61,7 @@ export class ShareService {
|
|||||||
maxExpiration.value !== 0 &&
|
maxExpiration.value !== 0 &&
|
||||||
(expiresNever ||
|
(expiresNever ||
|
||||||
parsedExpiration >
|
parsedExpiration >
|
||||||
moment()
|
moment().add(maxExpiration.value, maxExpiration.unit).toDate())
|
||||||
.add(maxExpiration.value, maxExpiration.unit)
|
|
||||||
.toDate())
|
|
||||||
) {
|
) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
"Expiration date exceeds maximum expiration date",
|
"Expiration date exceeds maximum expiration date",
|
||||||
|
|||||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-frontend",
|
"name": "pingvin-share-frontend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pingvin-share-frontend",
|
"name": "pingvin-share-frontend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share-frontend",
|
"name": "pingvin-share-frontend",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
|
|||||||
@@ -96,7 +96,9 @@ const AdminConfigInput = ({
|
|||||||
{configVariable.type == "timespan" && (
|
{configVariable.type == "timespan" && (
|
||||||
<TimespanInput
|
<TimespanInput
|
||||||
value={stringToTimespan(configVariable.value)}
|
value={stringToTimespan(configVariable.value)}
|
||||||
onChange={(timespan) => onValueChange(configVariable, timespanToString(timespan))}
|
onChange={(timespan) =>
|
||||||
|
onValueChange(configVariable, timespanToString(timespan))
|
||||||
|
}
|
||||||
w={201}
|
w={201}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,81 +3,86 @@ import { Timespan } from "../../types/timespan.type";
|
|||||||
import { NativeSelect, NumberInput } from "@mantine/core";
|
import { NativeSelect, NumberInput } from "@mantine/core";
|
||||||
import useTranslate from "../../hooks/useTranslate.hook";
|
import useTranslate from "../../hooks/useTranslate.hook";
|
||||||
|
|
||||||
const TimespanInput = ({ label, value, onChange, ...restProps }: {
|
const TimespanInput = ({
|
||||||
label?: string,
|
label,
|
||||||
value: Timespan,
|
value,
|
||||||
onChange: (timespan: Timespan) => void,
|
onChange,
|
||||||
[key: string]: any,
|
...restProps
|
||||||
|
}: {
|
||||||
|
label?: string;
|
||||||
|
value: Timespan;
|
||||||
|
onChange: (timespan: Timespan) => void;
|
||||||
|
[key: string]: any;
|
||||||
}) => {
|
}) => {
|
||||||
const [unit, setUnit] = useState(value.unit);
|
const [unit, setUnit] = useState(value.unit);
|
||||||
const [inputValue, setInputValue] = useState(value.value);
|
const [inputValue, setInputValue] = useState(value.value);
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
|
|
||||||
const version = inputValue == 1 ? "singular" : "plural";
|
|
||||||
const unitSelect = (
|
|
||||||
<NativeSelect
|
|
||||||
data={[
|
|
||||||
{
|
|
||||||
value: "minutes",
|
|
||||||
label: t(`upload.modal.expires.minute-${version}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "hours",
|
|
||||||
label: t(`upload.modal.expires.hour-${version}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "days",
|
|
||||||
label: t(`upload.modal.expires.day-${version}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "weeks",
|
|
||||||
label: t(`upload.modal.expires.week-${version}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "months",
|
|
||||||
label: t(`upload.modal.expires.month-${version}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "years",
|
|
||||||
label: t(`upload.modal.expires.year-${version}`),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
value={unit}
|
|
||||||
rightSectionWidth={28}
|
|
||||||
styles={{
|
|
||||||
input: {
|
|
||||||
fontWeight: 500,
|
|
||||||
borderTopLeftRadius: 0,
|
|
||||||
borderBottomLeftRadius: 0,
|
|
||||||
width: 120,
|
|
||||||
marginRight: -2,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onChange={event => {
|
|
||||||
const unit = event.currentTarget.value as Timespan["unit"];
|
|
||||||
setUnit(unit);
|
|
||||||
onChange({ value: inputValue, unit });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
const version = inputValue == 1 ? "singular" : "plural";
|
||||||
<NumberInput
|
const unitSelect = (
|
||||||
label={label}
|
<NativeSelect
|
||||||
value={inputValue}
|
data={[
|
||||||
min={0}
|
{
|
||||||
max={999999}
|
value: "minutes",
|
||||||
precision={0}
|
label: t(`upload.modal.expires.minute-${version}`),
|
||||||
rightSection={unitSelect}
|
},
|
||||||
rightSectionWidth={120}
|
{
|
||||||
onChange={value => {
|
value: "hours",
|
||||||
const inputVal = value || 0;
|
label: t(`upload.modal.expires.hour-${version}`),
|
||||||
setInputValue(inputVal);
|
},
|
||||||
onChange({ value: inputVal, unit });
|
{
|
||||||
}}
|
value: "days",
|
||||||
{...restProps}
|
label: t(`upload.modal.expires.day-${version}`),
|
||||||
/>
|
},
|
||||||
);
|
{
|
||||||
|
value: "weeks",
|
||||||
|
label: t(`upload.modal.expires.week-${version}`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "months",
|
||||||
|
label: t(`upload.modal.expires.month-${version}`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "years",
|
||||||
|
label: t(`upload.modal.expires.year-${version}`),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value={unit}
|
||||||
|
rightSectionWidth={28}
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
fontWeight: 500,
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
width: 120,
|
||||||
|
marginRight: -2,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onChange={(event) => {
|
||||||
|
const unit = event.currentTarget.value as Timespan["unit"];
|
||||||
|
setUnit(unit);
|
||||||
|
onChange({ value: inputValue, unit });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NumberInput
|
||||||
|
label={label}
|
||||||
|
value={inputValue}
|
||||||
|
min={0}
|
||||||
|
max={999999}
|
||||||
|
precision={0}
|
||||||
|
rightSection={unitSelect}
|
||||||
|
rightSectionWidth={120}
|
||||||
|
onChange={(value) => {
|
||||||
|
const inputVal = value || 0;
|
||||||
|
setInputValue(inputVal);
|
||||||
|
onChange({ value: inputVal, unit });
|
||||||
|
}}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TimespanInput;
|
export default TimespanInput;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import useTranslate, {
|
|||||||
translateOutsideContext,
|
translateOutsideContext,
|
||||||
} from "../../../hooks/useTranslate.hook";
|
} from "../../../hooks/useTranslate.hook";
|
||||||
import shareService from "../../../services/share.service";
|
import shareService from "../../../services/share.service";
|
||||||
|
import { Timespan } from "../../../types/timespan.type";
|
||||||
import { getExpirationPreview } from "../../../utils/date.util";
|
import { getExpirationPreview } from "../../../utils/date.util";
|
||||||
import toast from "../../../utils/toast.util";
|
import toast from "../../../utils/toast.util";
|
||||||
import FileSizeInput from "../../core/FileSizeInput";
|
import FileSizeInput from "../../core/FileSizeInput";
|
||||||
@@ -28,7 +29,7 @@ import showCompletedReverseShareModal from "./showCompletedReverseShareModal";
|
|||||||
const showCreateReverseShareModal = (
|
const showCreateReverseShareModal = (
|
||||||
modals: ModalsContextProps,
|
modals: ModalsContextProps,
|
||||||
showSendEmailNotificationOption: boolean,
|
showSendEmailNotificationOption: boolean,
|
||||||
maxExpirationInHours: number,
|
maxExpiration: Timespan,
|
||||||
getReverseShares: () => void,
|
getReverseShares: () => void,
|
||||||
) => {
|
) => {
|
||||||
const t = translateOutsideContext();
|
const t = translateOutsideContext();
|
||||||
@@ -38,7 +39,7 @@ const showCreateReverseShareModal = (
|
|||||||
<Body
|
<Body
|
||||||
showSendEmailNotificationOption={showSendEmailNotificationOption}
|
showSendEmailNotificationOption={showSendEmailNotificationOption}
|
||||||
getReverseShares={getReverseShares}
|
getReverseShares={getReverseShares}
|
||||||
maxExpirationInHours={maxExpirationInHours}
|
maxExpiration={maxExpiration}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -47,12 +48,13 @@ const showCreateReverseShareModal = (
|
|||||||
const Body = ({
|
const Body = ({
|
||||||
getReverseShares,
|
getReverseShares,
|
||||||
showSendEmailNotificationOption,
|
showSendEmailNotificationOption,
|
||||||
maxExpirationInHours,
|
maxExpiration,
|
||||||
}: {
|
}: {
|
||||||
getReverseShares: () => void;
|
getReverseShares: () => void;
|
||||||
showSendEmailNotificationOption: boolean;
|
showSendEmailNotificationOption: boolean;
|
||||||
maxExpirationInHours: number;
|
maxExpiration: Timespan;
|
||||||
}) => {
|
}) => {
|
||||||
|
console.log(maxExpiration);
|
||||||
const modals = useModals();
|
const modals = useModals();
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
|
|
||||||
@@ -91,13 +93,17 @@ const Body = ({
|
|||||||
) as moment.unitOfTime.DurationConstructor,
|
) as moment.unitOfTime.DurationConstructor,
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
maxExpirationInHours != 0 &&
|
maxExpiration.value != 0 &&
|
||||||
expirationDate.isAfter(moment().add(maxExpirationInHours, "hours"))
|
expirationDate.isAfter(
|
||||||
|
moment().add(maxExpiration.value, maxExpiration.unit),
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
form.setFieldError(
|
form.setFieldError(
|
||||||
"expiration_num",
|
"expiration_num",
|
||||||
t("upload.modal.expires.error.too-long", {
|
t("upload.modal.expires.error.too-long", {
|
||||||
max: moment.duration(maxExpirationInHours, "hours").humanize(),
|
max: moment
|
||||||
|
.duration(maxExpiration.value, maxExpiration.unit)
|
||||||
|
.humanize(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -184,7 +184,10 @@ const CreateUploadModalBody = ({
|
|||||||
options.maxExpiration.value != 0 &&
|
options.maxExpiration.value != 0 &&
|
||||||
(form.values.never_expires ||
|
(form.values.never_expires ||
|
||||||
expirationDate.isAfter(
|
expirationDate.isAfter(
|
||||||
moment().add(options.maxExpiration.value, options.maxExpiration.unit),
|
moment().add(
|
||||||
|
options.maxExpiration.value,
|
||||||
|
options.maxExpiration.unit,
|
||||||
|
),
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
form.setFieldError(
|
form.setFieldError(
|
||||||
|
|||||||
@@ -31,8 +31,7 @@ const get = (key: string, configVariables: Config[]): any => {
|
|||||||
if (configVariable.type == "boolean") return value == "true";
|
if (configVariable.type == "boolean") return value == "true";
|
||||||
if (configVariable.type == "string" || configVariable.type == "text")
|
if (configVariable.type == "string" || configVariable.type == "text")
|
||||||
return value;
|
return value;
|
||||||
if (configVariable.type == "timespan")
|
if (configVariable.type == "timespan") return stringToTimespan(value);
|
||||||
return stringToTimespan(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const finishSetup = async (): Promise<AdminConfig[]> => {
|
const finishSetup = async (): Promise<AdminConfig[]> => {
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
export type TimeUnit = "minutes" | "hours" | "days" | "weeks" | "months" | "years";
|
export type TimeUnit =
|
||||||
|
| "minutes"
|
||||||
|
| "hours"
|
||||||
|
| "days"
|
||||||
|
| "weeks"
|
||||||
|
| "months"
|
||||||
|
| "years";
|
||||||
export type Timespan = { value: number; unit: TimeUnit };
|
export type Timespan = { value: number; unit: TimeUnit };
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export const getExpirationPreview = (
|
|||||||
|
|
||||||
export const timespanToString = (timespan: Timespan) => {
|
export const timespanToString = (timespan: Timespan) => {
|
||||||
return `${timespan.value} ${timespan.unit}`;
|
return `${timespan.value} ${timespan.unit}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const stringToTimespan = (value: string): Timespan => {
|
export const stringToTimespan = (value: string): Timespan => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"conventional-changelog-cli": "^3.0.0"
|
"conventional-changelog-cli": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pingvin-share",
|
"name": "pingvin-share",
|
||||||
"version": "1.8.0",
|
"version": "1.8.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "cd frontend && npm run format && cd ../backend && npm run format",
|
"format": "cd frontend && npm run format && cd ../backend && npm run format",
|
||||||
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",
|
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",
|
||||||
|
|||||||
Reference in New Issue
Block a user