chore: migrate to @db.Timestamptz(3) and remove luxon dependency (#5283)
* feat: remove deprecated env sync * feat: using infraConfig in bootstrap * chore: migrate to TIMESTAMPTZ and remove luxon dependency * chore: remove luxon deps * Revert "feat: using infraConfig in bootstrap" This reverts commit 147dba632f095dad816afdd4e46ed736e8a3b8ff. * chore: cleanup
This commit is contained in:
parent
28ce90234f
commit
8f5eed5151
13 changed files with 128 additions and 89 deletions
|
|
@ -60,7 +60,6 @@
|
|||
"graphql-subscriptions": "3.0.0",
|
||||
"handlebars": "4.7.8",
|
||||
"io-ts": "2.2.22",
|
||||
"luxon": "3.7.1",
|
||||
"morgan": "1.10.1",
|
||||
"nodemailer": "7.0.5",
|
||||
"passport": "0.7.0",
|
||||
|
|
@ -86,7 +85,6 @@
|
|||
"@types/cookie-parser": "1.4.9",
|
||||
"@types/express": "5.0.3",
|
||||
"@types/jest": "30.0.0",
|
||||
"@types/luxon": "3.6.2",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"@types/passport-github2": "1.2.9",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Account" ALTER COLUMN "loggedIn" SET DATA TYPE TIMESTAMPTZ(3) USING "loggedIn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "InfraConfig" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "InfraToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "InvitedUsers" ALTER COLUMN "invitedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "invitedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "PersonalAccessToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Shortcode" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "TeamCollection" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "TeamRequest" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "lastLoggedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "lastLoggedOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "lastActiveOn" SET DATA TYPE TIMESTAMPTZ(3) USING "lastActiveOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "UserCollection" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "UserHistory" ALTER COLUMN "executedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "executedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "UserRequest" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "UserSettings" ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "VerificationToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC';
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ model TeamCollection {
|
|||
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
orderIndex Int
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model TeamRequest {
|
||||
|
|
@ -64,8 +64,8 @@ model TeamRequest {
|
|||
title String
|
||||
request Json
|
||||
orderIndex Int
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model Shortcode {
|
||||
|
|
@ -74,8 +74,8 @@ model Shortcode {
|
|||
embedProperties Json?
|
||||
creatorUid String?
|
||||
User User? @relation(fields: [creatorUid], references: [uid])
|
||||
createdOn DateTime @default(now())
|
||||
updatedOn DateTime @default(now()) @updatedAt
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @default(now()) @updatedAt @db.Timestamptz(3)
|
||||
|
||||
@@unique(fields: [id, creatorUid], name: "creator_uid_shortcode_unique")
|
||||
}
|
||||
|
|
@ -104,9 +104,9 @@ model User {
|
|||
userRequests UserRequest[]
|
||||
currentRESTSession Json?
|
||||
currentGQLSession Json?
|
||||
lastLoggedOn DateTime? @db.Timestamp(3)
|
||||
lastActiveOn DateTime? @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
lastLoggedOn DateTime? @db.Timestamptz(3)
|
||||
lastActiveOn DateTime? @db.Timestamptz(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
invitedUsers InvitedUsers[]
|
||||
shortcodes Shortcode[]
|
||||
personalAccessTokens PersonalAccessToken[]
|
||||
|
|
@ -121,7 +121,7 @@ model Account {
|
|||
providerRefreshToken String?
|
||||
providerAccessToken String?
|
||||
providerScope String?
|
||||
loggedIn DateTime @default(now()) @db.Timestamp(3)
|
||||
loggedIn DateTime @default(now()) @db.Timestamptz(3)
|
||||
|
||||
@@unique(fields: [provider, providerAccountId], name: "verifyProviderAccount")
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ model VerificationToken {
|
|||
token String @unique @default(cuid())
|
||||
userUid String
|
||||
user User @relation(fields: [userUid], references: [uid], onDelete: Cascade)
|
||||
expiresOn DateTime @db.Timestamp(3)
|
||||
expiresOn DateTime @db.Timestamptz(3)
|
||||
|
||||
@@unique(fields: [deviceIdentifier, token], name: "passwordless_deviceIdentifier_tokens")
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ model UserSettings {
|
|||
userUid String @unique
|
||||
user User @relation(fields: [userUid], references: [uid], onDelete: Cascade)
|
||||
properties Json
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model UserHistory {
|
||||
|
|
@ -152,7 +152,7 @@ model UserHistory {
|
|||
request Json
|
||||
responseMetadata Json
|
||||
isStarred Boolean
|
||||
executedOn DateTime @default(now()) @db.Timestamp(3)
|
||||
executedOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
enum ReqType {
|
||||
|
|
@ -174,7 +174,7 @@ model InvitedUsers {
|
|||
user User @relation(fields: [adminUid], references: [uid], onDelete: Cascade)
|
||||
adminEmail String
|
||||
inviteeEmail String @unique
|
||||
invitedOn DateTime @default(now()) @db.Timestamp(3)
|
||||
invitedOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model UserRequest {
|
||||
|
|
@ -187,8 +187,8 @@ model UserRequest {
|
|||
request Json
|
||||
type ReqType
|
||||
orderIndex Int
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model UserCollection {
|
||||
|
|
@ -203,8 +203,8 @@ model UserCollection {
|
|||
data Json?
|
||||
orderIndex Int
|
||||
type ReqType
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
enum TeamAccessRole {
|
||||
|
|
@ -217,10 +217,10 @@ model InfraConfig {
|
|||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
value String?
|
||||
lastSyncedEnvFileValue String?
|
||||
lastSyncedEnvFileValue String? // deprecated, use `value` instead
|
||||
isEncrypted Boolean @default(false) // Use case: Let's say, Admin wants to store a Secret Key, but doesn't want to store it in plain text in `value` column
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model PersonalAccessToken {
|
||||
|
|
@ -229,9 +229,9 @@ model PersonalAccessToken {
|
|||
user User @relation(fields: [userUid], references: [uid], onDelete: Cascade)
|
||||
label String
|
||||
token String @unique @default(uuid())
|
||||
expiresOn DateTime? @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamp(3)
|
||||
expiresOn DateTime? @db.Timestamptz(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @updatedAt @db.Timestamptz(3)
|
||||
}
|
||||
|
||||
model InfraToken {
|
||||
|
|
@ -239,7 +239,7 @@ model InfraToken {
|
|||
creatorUid String
|
||||
label String
|
||||
token String @unique @default(uuid())
|
||||
expiresOn DateTime? @db.Timestamp(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||
updatedOn DateTime @default(now()) @db.Timestamp(3)
|
||||
expiresOn DateTime? @db.Timestamptz(3)
|
||||
createdOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedOn DateTime @default(now()) @db.Timestamptz(3)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { MailerService } from 'src/mailer/mailer.service';
|
|||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { VerifyMagicDto } from './dto/verify-magic.dto';
|
||||
import { DateTime } from 'luxon';
|
||||
import * as argon2 from 'argon2';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import * as O from 'fp-ts/Option';
|
||||
|
|
@ -52,14 +51,15 @@ export class AuthService {
|
|||
const salt = await bcrypt.genSalt(
|
||||
parseInt(this.configService.get('INFRA.TOKEN_SALT_COMPLEXITY')),
|
||||
);
|
||||
const expiresOn = DateTime.now()
|
||||
.plus({
|
||||
hours: parseInt(
|
||||
this.configService.get('INFRA.MAGIC_LINK_TOKEN_VALIDITY'),
|
||||
),
|
||||
})
|
||||
.toISO()
|
||||
.toString();
|
||||
|
||||
// Calculate expiration time by adding hours to current time
|
||||
let validityInHours = parseInt(
|
||||
this.configService.get('INFRA.MAGIC_LINK_TOKEN_VALIDITY'),
|
||||
);
|
||||
if (isNaN(validityInHours)) validityInHours = 24; // Default: 24 hours
|
||||
|
||||
const expiresOn = new Date();
|
||||
expiresOn.setHours(expiresOn.getHours() + validityInHours);
|
||||
|
||||
const idToken = await this.prisma.verificationToken.create({
|
||||
data: {
|
||||
|
|
@ -296,8 +296,8 @@ export class AuthService {
|
|||
);
|
||||
}
|
||||
|
||||
const currentTime = DateTime.now().toISO();
|
||||
if (currentTime > passwordlessTokens.value.expiresOn.toISOString())
|
||||
const currentTime = new Date();
|
||||
if (currentTime > passwordlessTokens.value.expiresOn)
|
||||
return E.left({
|
||||
message: MAGIC_LINK_EXPIRED,
|
||||
statusCode: HttpStatus.UNAUTHORIZED,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { DateTime } from 'luxon';
|
||||
import { AuthTokens } from 'src/types/AuthTokens';
|
||||
import { Response } from 'express';
|
||||
import * as cookie from 'cookie';
|
||||
|
|
@ -43,29 +42,29 @@ export const authCookieHandler = (
|
|||
redirectUrl: string | null,
|
||||
configService: ConfigService,
|
||||
) => {
|
||||
const currentTime = DateTime.now();
|
||||
const accessTokenValidity = currentTime
|
||||
.plus({
|
||||
milliseconds: parseInt(configService.get('INFRA.ACCESS_TOKEN_VALIDITY')),
|
||||
})
|
||||
.toMillis();
|
||||
const refreshTokenValidity = currentTime
|
||||
.plus({
|
||||
milliseconds: parseInt(configService.get('INFRA.REFRESH_TOKEN_VALIDITY')),
|
||||
})
|
||||
.toMillis();
|
||||
// Calculate token validity periods in milliseconds
|
||||
let accessTokenValidityInMs = parseInt(
|
||||
configService.get('INFRA.ACCESS_TOKEN_VALIDITY'),
|
||||
);
|
||||
let refreshTokenValidityInMs = parseInt(
|
||||
configService.get('INFRA.REFRESH_TOKEN_VALIDITY'),
|
||||
);
|
||||
|
||||
// Set default values if parsing results in NaN
|
||||
if (isNaN(accessTokenValidityInMs)) accessTokenValidityInMs = 86400000; // Default: 1 day
|
||||
if (isNaN(refreshTokenValidityInMs)) refreshTokenValidityInMs = 604800000; // Default: 7 days
|
||||
|
||||
res.cookie(AuthTokenType.ACCESS_TOKEN, authTokens.access_token, {
|
||||
httpOnly: true,
|
||||
secure: configService.get('INFRA.ALLOW_SECURE_COOKIES') === 'true',
|
||||
sameSite: 'lax',
|
||||
maxAge: accessTokenValidity,
|
||||
maxAge: Date.now() + accessTokenValidityInMs,
|
||||
});
|
||||
res.cookie(AuthTokenType.REFRESH_TOKEN, authTokens.refresh_token, {
|
||||
httpOnly: true,
|
||||
secure: configService.get('INFRA.ALLOW_SECURE_COOKIES') === 'true',
|
||||
sameSite: 'lax',
|
||||
maxAge: refreshTokenValidity,
|
||||
maxAge: Date.now() + refreshTokenValidityInMs,
|
||||
});
|
||||
|
||||
if (!redirect) {
|
||||
|
|
|
|||
|
|
@ -26,12 +26,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy) {
|
|||
});
|
||||
}
|
||||
|
||||
async validate(
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
profile,
|
||||
done,
|
||||
) {
|
||||
async validate(accessToken: string, refreshToken: string, profile, done) {
|
||||
const email = profile?.emails?.[0]?.value;
|
||||
|
||||
if (!validateEmail(email))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { DateTime } from 'luxon';
|
||||
import {
|
||||
INFRA_TOKEN_EXPIRED,
|
||||
INFRA_TOKEN_HEADER_MISSING,
|
||||
|
|
@ -37,8 +36,8 @@ export class InfraTokenGuard implements CanActivate {
|
|||
if (infraToken === null)
|
||||
throw new UnauthorizedException(INFRA_TOKEN_INVALID_TOKEN);
|
||||
|
||||
const currentTime = DateTime.now().toISO();
|
||||
if (currentTime > infraToken.expiresOn?.toISOString()) {
|
||||
// Check if token has expired (if expiresOn is set)
|
||||
if (infraToken.expiresOn && new Date() > infraToken.expiresOn) {
|
||||
throw new UnauthorizedException(INFRA_TOKEN_EXPIRED);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
import { Request } from 'express';
|
||||
import { AccessTokenService } from 'src/access-token/access-token.service';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ACCESS_TOKEN_EXPIRED, ACCESS_TOKEN_INVALID } from 'src/errors';
|
||||
import { createCLIErrorResponse } from 'src/access-token/helper';
|
||||
@Injectable()
|
||||
|
|
@ -28,15 +27,23 @@ export class PATAuthGuard implements CanActivate {
|
|||
throw new BadRequestException(
|
||||
createCLIErrorResponse(ACCESS_TOKEN_INVALID),
|
||||
);
|
||||
|
||||
request.user = userAccessToken.right.user;
|
||||
|
||||
const accessToken = userAccessToken.right;
|
||||
if (accessToken.expiresOn === null) return true;
|
||||
|
||||
const today = DateTime.now().toISO();
|
||||
if (accessToken.expiresOn.toISOString() > today) return true;
|
||||
// If token has no expiration, it's valid
|
||||
if (accessToken.expiresOn === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new BadRequestException(createCLIErrorResponse(ACCESS_TOKEN_EXPIRED));
|
||||
// Check if token has expired
|
||||
if (new Date() > accessToken.expiresOn) {
|
||||
throw new BadRequestException(
|
||||
createCLIErrorResponse(ACCESS_TOKEN_EXPIRED),
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
|
|
|
|||
|
|
@ -511,7 +511,7 @@
|
|||
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
<p class="f-fallback sub align-center">© 2021 Hoppscotch</p>
|
||||
<p class="f-fallback sub align-center">© 2025 Hoppscotch</p>
|
||||
<p class="f-fallback sub align-center">12 New Fetter Lane, London, United Kingdom, EC4A 1JP.</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@
|
|||
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
<p class="f-fallback sub align-center">© 2021 Hoppscotch</p>
|
||||
<p class="f-fallback sub align-center">© 2025 Hoppscotch</p>
|
||||
<p class="f-fallback sub align-center">12 New Fetter Lane, London, United Kingdom, EC4A 1JP.</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -266,12 +266,12 @@ export function escapeSqlLikeString(str: string) {
|
|||
/**
|
||||
* Calculate the expiration date of the token
|
||||
*
|
||||
* @param expiresOn Number of days the token is valid for
|
||||
* @param expiresInDays Number of days the token is valid for
|
||||
* @returns Date object of the expiration date
|
||||
*/
|
||||
export function calculateExpirationDate(expiresOn: null | number) {
|
||||
if (expiresOn === null) return null;
|
||||
return new Date(Date.now() + expiresOn * 24 * 60 * 60 * 1000);
|
||||
export function calculateExpirationDate(expiresInDays: null | number) {
|
||||
if (expiresInDays === null) return null;
|
||||
return new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -241,9 +241,6 @@ importers:
|
|||
io-ts:
|
||||
specifier: 2.2.22
|
||||
version: 2.2.22(fp-ts@2.16.10)
|
||||
luxon:
|
||||
specifier: 3.7.1
|
||||
version: 3.7.1
|
||||
morgan:
|
||||
specifier: 1.10.1
|
||||
version: 1.10.1
|
||||
|
|
@ -314,9 +311,6 @@ importers:
|
|||
'@types/jest':
|
||||
specifier: 30.0.0
|
||||
version: 30.0.0
|
||||
'@types/luxon':
|
||||
specifier: 3.6.2
|
||||
version: 3.6.2
|
||||
'@types/node':
|
||||
specifier: 24.1.0
|
||||
version: 24.1.0
|
||||
|
|
@ -10917,10 +10911,6 @@ packages:
|
|||
resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
luxon@3.7.1:
|
||||
resolution: {integrity: sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
magic-string@0.25.9:
|
||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||
|
||||
|
|
@ -26933,8 +26923,6 @@ snapshots:
|
|||
|
||||
luxon@3.6.1: {}
|
||||
|
||||
luxon@3.7.1: {}
|
||||
|
||||
magic-string@0.25.9:
|
||||
dependencies:
|
||||
sourcemap-codec: 1.4.8
|
||||
|
|
|
|||
Loading…
Reference in a new issue