123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import { config } from "#config";
- import jwt from "jsonwebtoken";
- // база данных
- import { selPool, updPool } from "#db";
- import { sql } from "slonik";
- // types
- import { TokenPayload } from "../types/token-playload-type.js";
- import type { Response } from "express";
- import { z } from "zod";
- import { v7 } from "uuid";
- import { logger } from "#plugins/logger.js";
- const JWT_ACCESS_SECRET = config.JWT_ACCESS_SECRET || "";
- const JWT_REFRESH_SECRET = config.JWT_REFRESH_SECRET || "";
- const ACCESS_TOKEN_LIFETIME_MINS = config.ACCESS_TOKEN_LIFETIME_MINS || 15;
- const REFRESH_TOKEN_LIFETIME_DAYS = config.REFRESH_TOKEN_LIFETIME_DAYS || 30;
- class TokenService {
- /**
- * генерирует пару токенов: accessToken и refreshToken
- * @param payload - данные, которые будут зашифрованы в токенах
- * @returns обьект с двумя свойствами: accessToken и refreshToken
- */
- generateTokens(payload: z.infer<typeof TokenPayload>): {
- accessToken: string;
- refreshToken: string;
- } {
- const accessToken = jwt.sign(payload, JWT_ACCESS_SECRET, {
- expiresIn: `${ACCESS_TOKEN_LIFETIME_MINS}m`,
- });
- const refreshToken = jwt.sign(payload, JWT_REFRESH_SECRET, {
- expiresIn: `${REFRESH_TOKEN_LIFETIME_DAYS}d`,
- });
- return {
- accessToken,
- refreshToken,
- };
- }
- /**
- * вставляет refreshToken в базу данных
- * @param userId - id пользователя
- * @param refreshToken - токен, который будет вставлен
- */
- async insertRefreshToken(userId: string, refreshToken: string) {
- const id = v7();
- await updPool.query(
- sql.unsafe`
- insert into usr.user_refresh_tokens
- (token_id, user_id, refresh_token)
- values
- (${id}, ${userId}, ${refreshToken})
- `,
- );
- }
- /**
- * обновляет refreshToken в базе данных
- * @param userId - id пользователя
- * @param oldRefreshToken - старый токен
- * @param newRefreshToken - новый токен
- */
- async updateRefreshToken(
- userId: string,
- oldRefreshToken: string,
- newRefreshToken: string,
- ) {
- await updPool.query(
- sql.unsafe`
- update
- usr.user_refresh_tokens
- set
- refresh_token = ${newRefreshToken}
- where
- user_id = ${userId} and
- refresh_token = ${oldRefreshToken}
- `,
- );
- }
- /**
- * удаляет refreshToken из базы данных
- * @param userId - id пользователя
- * @param refreshToken - токен, который будет удален
- */
- async removeToken(userId: string, refreshToken: string) {
- await updPool.query(sql.unsafe`
- delete from
- usr.user_refresh_tokens
- where
- user_id = ${userId} and refresh_token = ${refreshToken}
- `);
- }
- /**
- * удаляет все токены пользователя по его id
- * @param userId - id пользователя
- */
- async removeAllUserTokens(userId: string) {
- await updPool.query(sql.unsafe`
- delete from
- usr.user_refresh_tokens
- where
- user_id = ${userId}
- `);
- }
- /**
- * проверяет acess токен и возвращает данные из него
- * @param token - токен
- * @returns данные из токена
- */
- validateAccessToken(token: string) {
- const userData = jwt.verify(token, JWT_ACCESS_SECRET);
- return TokenPayload.parse(userData);
- }
- /**
- * проверяет refresh токен и возвращает данные из него
- * @param token - токен
- * @returns данные из токена
- */
- validateRefreshToken(token: string) {
- const userData = jwt.verify(token, JWT_REFRESH_SECRET);
- return TokenPayload.parse(userData);
- }
- /**
- * Проверяет, существует ли refresh токен в базе данных
- * @param userId - id пользователя
- * @param refreshToken - токен, который будет проверен
- * @returns true, если токен существует, false - иначе
- */
- async refreshTokenIsExist(
- userId: string,
- refreshToken: string,
- ): Promise<boolean> {
- const tokenIsExist = await selPool.exists(
- sql.unsafe`
- select
- user_id
- from
- usr.user_refresh_tokens
- where
- user_id = ${userId} and refresh_token = ${refreshToken}`,
- );
- return tokenIsExist;
- }
- /**
- * установить refresh токен в cookie
- * @param res - объект Response
- * @param token - токен
- */
- setRefreshTokenInCookie(res: Response, token: string) {
- logger.silly(`setRefreshTokenInCookie ${token}`);
- res.cookie("refreshToken", token, {
- maxAge: config.REFRESH_TOKEN_LIFETIME_DAYS * 24 * 60 * 60 * 1000,
- httpOnly: true, //запрет на изменение пользователем
- // secure: true, //после включения https
- sameSite: "lax", // TODO: Разбраться
- });
- }
- }
- export default new TokenService();
|