feat: improve UI for timespan inputs on admin page (#726)
* Define Timestamp type * Implement Timestamp utils * Implement Timespan input * Use timestamp input on config page * Add timespan type to config services * Refactor maxExpiration to use timespan type across services and components * Update sessionDuration to use timespan type in config and adjust token expiration logic * Update localized strings
This commit is contained in:
@@ -306,11 +306,12 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async createRefreshToken(userId: string, idToken?: string) {
|
||||
const sessionDuration = this.config.get("general.sessionDuration");
|
||||
const { id, token } = await this.prisma.refreshToken.create({
|
||||
data: {
|
||||
userId,
|
||||
expiresAt: moment()
|
||||
.add(this.config.get("general.sessionDuration"), "hours")
|
||||
.add(sessionDuration.value, sessionDuration.unit)
|
||||
.toDate(),
|
||||
oauthIDToken: idToken,
|
||||
},
|
||||
@@ -341,14 +342,18 @@ export class AuthService {
|
||||
secure: isSecure,
|
||||
maxAge: 1000 * 60 * 60 * 24 * 30 * 3, // 3 months
|
||||
});
|
||||
if (refreshToken)
|
||||
if (refreshToken) {
|
||||
const now = moment();
|
||||
const sessionDuration = this.config.get("general.sessionDuration");
|
||||
const maxAge = moment(now).add(sessionDuration.value, sessionDuration.unit).diff(now);
|
||||
response.cookie("refresh_token", refreshToken, {
|
||||
path: "/api/auth/token",
|
||||
httpOnly: true,
|
||||
sameSite: "strict",
|
||||
secure: isSecure,
|
||||
maxAge: 1000 * 60 * 60 * this.config.get("general.sessionDuration"),
|
||||
maxAge,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import { Config } from "@prisma/client";
|
||||
import { EventEmitter } from "events";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { stringToTimespan } from "src/utils/date.util";
|
||||
|
||||
/**
|
||||
* ConfigService extends EventEmitter to allow listening for config updates,
|
||||
@@ -35,6 +36,8 @@ export class ConfigService extends EventEmitter {
|
||||
if (configVariable.type == "boolean") return value == "true";
|
||||
if (configVariable.type == "string" || configVariable.type == "text")
|
||||
return value;
|
||||
if (configVariable.type == "timespan")
|
||||
return stringToTimespan(value);
|
||||
}
|
||||
|
||||
async getByCategory(category: string) {
|
||||
@@ -94,7 +97,8 @@ export class ConfigService extends EventEmitter {
|
||||
} else if (
|
||||
typeof value != configVariable.type &&
|
||||
typeof value == "string" &&
|
||||
configVariable.type != "text"
|
||||
configVariable.type != "text" &&
|
||||
configVariable.type != "timespan"
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Config variable must be of type ${configVariable.type}`,
|
||||
@@ -132,6 +136,7 @@ export class ConfigService extends EventEmitter {
|
||||
condition: (value: number) => value >= 0 && value <= 9,
|
||||
message: "Zip compression level must be between 0 and 9",
|
||||
},
|
||||
// TODO add validation for timespan type
|
||||
];
|
||||
|
||||
const validation = validations.find((validation) => validation.key == key);
|
||||
|
||||
@@ -56,12 +56,13 @@ export class ShareService {
|
||||
|
||||
const expiresNever = moment(0).toDate() == parsedExpiration;
|
||||
|
||||
const maxExpiration = this.config.get("share.maxExpiration");
|
||||
if (
|
||||
this.config.get("share.maxExpiration") !== 0 &&
|
||||
maxExpiration.value !== 0 &&
|
||||
(expiresNever ||
|
||||
parsedExpiration >
|
||||
moment()
|
||||
.add(this.config.get("share.maxExpiration"), "hours")
|
||||
.add(maxExpiration.value, maxExpiration.unit)
|
||||
.toDate())
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
|
||||
@@ -10,3 +10,20 @@ export function parseRelativeDateToAbsolute(relativeDate: string) {
|
||||
)
|
||||
.toDate();
|
||||
}
|
||||
|
||||
type Timespan = {
|
||||
value: number;
|
||||
unit: "minutes" | "hours" | "days" | "weeks" | "months" | "years";
|
||||
};
|
||||
|
||||
export function stringToTimespan(value: string): Timespan {
|
||||
const [time, unit] = value.split(" ");
|
||||
return {
|
||||
value: parseInt(time),
|
||||
unit: unit as Timespan["unit"],
|
||||
};
|
||||
}
|
||||
|
||||
export function timespanToString(timespan: Timespan) {
|
||||
return `${timespan.value} ${timespan.unit}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user