auth defined test required
This commit is contained in:
@@ -8,12 +8,15 @@ import {
|
||||
Body,
|
||||
HttpCode,
|
||||
UseGuards,
|
||||
Req,
|
||||
} from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { userLoginValidator } from './login/dtoValidator';
|
||||
import { userSelectValidator } from './select/dtoValidator';
|
||||
import { userLogoutValidator } from './logout/dtoValidator';
|
||||
import { AuthControlGuard } from '../middleware/access-control.guard';
|
||||
import { userCreatePasswordValidator } from './password/create/dtoValidator';
|
||||
import { userChangePasswordValidator } from './password/change/dtoValidator';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
@@ -34,15 +37,18 @@ export class AuthController {
|
||||
|
||||
@Post('/password/create')
|
||||
@HttpCode(200)
|
||||
async createPassword() {
|
||||
return { message: 'Password created successfully' };
|
||||
async createPassword(@Body() query: userCreatePasswordValidator) {
|
||||
return await this.authService.createPassword(query);
|
||||
}
|
||||
|
||||
@Post('/password/change')
|
||||
@HttpCode(200)
|
||||
@UseGuards(AuthControlGuard)
|
||||
async changePassword() {
|
||||
return { message: 'Password changed successfully' };
|
||||
async changePassword(
|
||||
@Body() query: userChangePasswordValidator,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
return await this.authService.changePassword(query, req);
|
||||
}
|
||||
|
||||
@Post('/password/reset')
|
||||
|
||||
@@ -21,8 +21,8 @@ import { DisconnectService } from './disconnect/disconnect.service';
|
||||
LogoutService,
|
||||
SelectService,
|
||||
CreatePasswordService,
|
||||
ResetPasswordService,
|
||||
ChangePasswordService,
|
||||
ResetPasswordService,
|
||||
VerifyOtpService,
|
||||
DisconnectService,
|
||||
PrismaService,
|
||||
|
||||
@@ -40,8 +40,8 @@ export class AuthService {
|
||||
return await this.createPasswordService.run(dto);
|
||||
}
|
||||
|
||||
async changePassword(dto: any) {
|
||||
return await this.changePasswordService.run(dto);
|
||||
async changePassword(dto: any, req: Request) {
|
||||
return await this.changePasswordService.run(dto, req);
|
||||
}
|
||||
|
||||
async resetPassword(dto: any) {
|
||||
|
||||
@@ -1,8 +1,196 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import {
|
||||
Injectable,
|
||||
BadRequestException,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { userChangePasswordValidator } from './dtoValidator';
|
||||
import { RedisHandlers } from '@/src/utils/auth/redis_handlers';
|
||||
import { PasswordHandlers } from '@/src/utils/auth/login_handler';
|
||||
|
||||
@Injectable()
|
||||
export class ChangePasswordService {
|
||||
async run(dto: any) {
|
||||
return dto;
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly redis: RedisHandlers,
|
||||
private readonly passHandlers: PasswordHandlers,
|
||||
) {}
|
||||
|
||||
private async syncPasswordHistory(
|
||||
foundUser: any,
|
||||
dto: userChangePasswordValidator,
|
||||
hashPassword: string,
|
||||
) {
|
||||
const passwordHistory = await this.prisma.password_history.findFirst({
|
||||
where: { userUUID: foundUser.uu_id },
|
||||
});
|
||||
console.log('passwordHistory', passwordHistory);
|
||||
console.log('dto', dto);
|
||||
console.log('hashPassword', hashPassword);
|
||||
|
||||
if (passwordHistory) {
|
||||
if (!passwordHistory.old_password_first) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else if (!passwordHistory.old_password_second) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_second: dto.password,
|
||||
old_password_second_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else if (!passwordHistory.old_password_third) {
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
old_password_third: dto.password,
|
||||
old_password_third_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const firstTimestamp = new Date(
|
||||
passwordHistory.old_password_first_modified_at,
|
||||
).getTime();
|
||||
const secondTimestamp = new Date(
|
||||
passwordHistory.old_password_second_modified_at,
|
||||
).getTime();
|
||||
const thirdTimestamp = new Date(
|
||||
passwordHistory.old_password_third_modified_at,
|
||||
).getTime();
|
||||
|
||||
let oldestIndex = 'first';
|
||||
let oldestTimestamp = firstTimestamp;
|
||||
|
||||
if (secondTimestamp < oldestTimestamp) {
|
||||
oldestIndex = 'second';
|
||||
oldestTimestamp = secondTimestamp;
|
||||
}
|
||||
if (thirdTimestamp < oldestTimestamp) {
|
||||
oldestIndex = 'third';
|
||||
}
|
||||
|
||||
await this.prisma.password_history.update({
|
||||
where: { id: passwordHistory.id },
|
||||
data: {
|
||||
password: hashPassword,
|
||||
...(oldestIndex === 'first'
|
||||
? {
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
}
|
||||
: oldestIndex === 'second'
|
||||
? {
|
||||
old_password_second: dto.password,
|
||||
old_password_second_modified_at: new Date(),
|
||||
}
|
||||
: {
|
||||
old_password_third: dto.password,
|
||||
old_password_third_modified_at: new Date(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await this.prisma.password_history.create({
|
||||
data: {
|
||||
userUUID: foundUser.uu_id,
|
||||
password: hashPassword,
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
old_password_second: '',
|
||||
old_password_second_modified_at: new Date(),
|
||||
old_password_third: '',
|
||||
old_password_third_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async run(dto: userChangePasswordValidator, req: Request) {
|
||||
const isValid = () => {
|
||||
const isOldPasswordDifferent = dto.password !== dto.oldPassword;
|
||||
const isPasswordMatchesWithRePassword = dto.password === dto.rePassword;
|
||||
return isOldPasswordDifferent && isPasswordMatchesWithRePassword;
|
||||
};
|
||||
|
||||
if (!isValid()) {
|
||||
throw new BadRequestException(
|
||||
'Passwords do not match or new password is the same as old password',
|
||||
);
|
||||
}
|
||||
const accessObject = await this.redis.getLoginFromRedis(req);
|
||||
const userFromRedis = accessObject?.value.users;
|
||||
if (!userFromRedis) {
|
||||
throw new UnauthorizedException('User not authenticated');
|
||||
}
|
||||
|
||||
const foundUser = await this.prisma.users.findFirstOrThrow({
|
||||
where: { uu_id: userFromRedis.uu_id },
|
||||
});
|
||||
|
||||
if (foundUser.password_token) {
|
||||
throw new BadRequestException('Set password first before changing');
|
||||
}
|
||||
const isPasswordValid = this.passHandlers.check_password(
|
||||
foundUser.uu_id,
|
||||
dto.oldPassword,
|
||||
foundUser.hash_password,
|
||||
);
|
||||
if (!isPasswordValid) {
|
||||
throw new UnauthorizedException('Invalid password');
|
||||
}
|
||||
|
||||
const passwordHistory = await this.prisma.password_history.findFirst({
|
||||
where: {
|
||||
userUUID: foundUser.uu_id,
|
||||
OR: [
|
||||
{
|
||||
old_password_first: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
old_password_second: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
old_password_third: {
|
||||
equals: dto.password,
|
||||
mode: 'insensitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
if (passwordHistory) {
|
||||
throw new UnauthorizedException(
|
||||
'Invalid password, new password can not be same as old password',
|
||||
);
|
||||
}
|
||||
|
||||
const hashPassword = this.passHandlers.create_hashed_password(
|
||||
foundUser.uu_id,
|
||||
dto.password,
|
||||
);
|
||||
await this.prisma.users.update({
|
||||
where: { id: foundUser.id },
|
||||
data: {
|
||||
hash_password: hashPassword,
|
||||
},
|
||||
});
|
||||
await this.syncPasswordHistory(foundUser, dto, hashPassword);
|
||||
return { message: 'Password changed successfully' };
|
||||
}
|
||||
}
|
||||
|
||||
14
ServicesApi/src/auth/password/change/dtoValidator.ts
Normal file
14
ServicesApi/src/auth/password/change/dtoValidator.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class userChangePasswordValidator {
|
||||
@IsString()
|
||||
oldPassword: string;
|
||||
|
||||
@IsString()
|
||||
password: string;
|
||||
|
||||
@IsString()
|
||||
rePassword: string;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,8 +1,70 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { userCreatePasswordValidator } from './dtoValidator';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import { PasswordHandlers } from '@/src/utils/auth/login_handler';
|
||||
import { Injectable, BadRequestException } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class CreatePasswordService {
|
||||
async run(dto: any) {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly passHandlers: PasswordHandlers,
|
||||
) {}
|
||||
|
||||
async run(dto: userCreatePasswordValidator) {
|
||||
if (dto.password !== dto.rePassword) {
|
||||
throw new BadRequestException('Passwords do not match');
|
||||
}
|
||||
const foundUser = await this.prisma.users.findFirstOrThrow({
|
||||
where: { password_token: dto.passwordToken },
|
||||
});
|
||||
|
||||
const passwordExpiryDate = new Date(foundUser.password_expiry_begins);
|
||||
const passwordExpiryDay = foundUser.password_expires_day;
|
||||
const dayInMilliseconds = 24 * 60 * 60 * 1000;
|
||||
console.log(
|
||||
'exp : ',
|
||||
passwordExpiryDate,
|
||||
passwordExpiryDay,
|
||||
dayInMilliseconds,
|
||||
);
|
||||
const today = new Date().getTime();
|
||||
const comparasionDate = new Date(
|
||||
passwordExpiryDate.getTime() + passwordExpiryDay * dayInMilliseconds,
|
||||
).getTime();
|
||||
if (today >= comparasionDate) {
|
||||
throw new BadRequestException(
|
||||
'Password token is expired contact to your admin',
|
||||
);
|
||||
}
|
||||
|
||||
const hashPassword = this.passHandlers.create_hashed_password(
|
||||
foundUser.uu_id,
|
||||
dto.password,
|
||||
);
|
||||
|
||||
const updatedUser = await this.prisma.users.update({
|
||||
where: { id: foundUser.id },
|
||||
data: {
|
||||
hash_password: hashPassword,
|
||||
password_token: '',
|
||||
password_expiry_begins: new Date(),
|
||||
},
|
||||
});
|
||||
console.log('updatedUser');
|
||||
console.dir(updatedUser);
|
||||
await this.prisma.password_history.create({
|
||||
data: {
|
||||
userUUID: foundUser.uu_id,
|
||||
password: hashPassword,
|
||||
old_password_first: dto.password,
|
||||
old_password_first_modified_at: new Date(),
|
||||
old_password_second: '',
|
||||
old_password_second_modified_at: new Date(),
|
||||
old_password_third: '',
|
||||
old_password_third_modified_at: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return { message: 'Password created successfully' };
|
||||
}
|
||||
}
|
||||
|
||||
12
ServicesApi/src/auth/password/create/dtoValidator.ts
Normal file
12
ServicesApi/src/auth/password/create/dtoValidator.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class userCreatePasswordValidator {
|
||||
@IsString()
|
||||
passwordToken: string;
|
||||
|
||||
@IsString()
|
||||
password: string;
|
||||
|
||||
@IsString()
|
||||
rePassword: string;
|
||||
}
|
||||
6
ServicesApi/src/auth/password/reset/dtoValidator.ts
Normal file
6
ServicesApi/src/auth/password/reset/dtoValidator.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class userResetPasswordValidator {
|
||||
@IsString()
|
||||
accessKey: string;
|
||||
}
|
||||
@@ -1,8 +1,36 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, BadRequestException } from '@nestjs/common';
|
||||
import { userResetPasswordValidator } from './dtoValidator';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
import { PasswordHandlers } from '@/src/utils/auth/login_handler';
|
||||
|
||||
@Injectable()
|
||||
export class ResetPasswordService {
|
||||
async run(dto: any) {
|
||||
return dto;
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly passHandlers: PasswordHandlers,
|
||||
) {}
|
||||
async run(dto: userResetPasswordValidator) {
|
||||
const foundUser = await this.prisma.users.findFirstOrThrow({
|
||||
where: {
|
||||
OR: [{ email: dto.accessKey }, { phone_number: dto.accessKey }],
|
||||
},
|
||||
});
|
||||
if (!foundUser) {
|
||||
throw new BadRequestException(
|
||||
'User not found. Please check your email or phone number',
|
||||
);
|
||||
}
|
||||
|
||||
await this.prisma.users.update({
|
||||
where: { id: foundUser.id },
|
||||
data: {
|
||||
password_token: this.passHandlers.generateRefreshToken(),
|
||||
password_expiry_begins: new Date(),
|
||||
password_expires_day: 30,
|
||||
},
|
||||
});
|
||||
return {
|
||||
message: 'Password reset token sent successfully',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
8
ServicesApi/src/auth/password/verify-otp/dtoValidator.ts
Normal file
8
ServicesApi/src/auth/password/verify-otp/dtoValidator.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { IsNumber, Max, Min } from 'class-validator';
|
||||
|
||||
export class userVerifyOtpValidator {
|
||||
@IsNumber()
|
||||
@Min(6)
|
||||
@Max(6)
|
||||
otp: number;
|
||||
}
|
||||
@@ -1,7 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { authenticator } from 'otplib';
|
||||
import * as qrcode from 'qrcode';
|
||||
import { PrismaService } from '@/src/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class VerifyOtpService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
generate2FASecret(username: string) {
|
||||
const serviceName = 'BenimUygulamam';
|
||||
const secret = authenticator.generateSecret();
|
||||
const otpauthUrl = authenticator.keyuri(username, serviceName, secret);
|
||||
return { secret, otpauthUrl };
|
||||
}
|
||||
|
||||
async generateQRCode(otpauthUrl: string): Promise<string> {
|
||||
return await qrcode.toDataURL(otpauthUrl);
|
||||
}
|
||||
|
||||
verify2FACode(code: string, secret: string): boolean {
|
||||
return authenticator.verify({ token: code, secret });
|
||||
}
|
||||
|
||||
async run(dto: any) {
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -6,30 +6,13 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { RedisHandlers } from '@/src/utils/auth/redis_handlers';
|
||||
|
||||
const getAccessTokenFromHeader = (req: Request): string => {
|
||||
console.log(req.headers);
|
||||
const token = req.headers['acs'];
|
||||
if (!token) {
|
||||
throw new ForbiddenException('Access token header is missing');
|
||||
}
|
||||
return token;
|
||||
};
|
||||
|
||||
const getSelectTokenFromHeader = (req: Request): string => {
|
||||
const token = req.headers['slc'];
|
||||
if (!token) {
|
||||
throw new ForbiddenException('Select token header is missing');
|
||||
}
|
||||
return token;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class AuthControlGuard implements CanActivate {
|
||||
constructor(private cacheService: RedisHandlers) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
const accessToken = getAccessTokenFromHeader(req);
|
||||
const accessToken = this.cacheService.mergeLoginKey(req);
|
||||
console.log('AuthControlGuard', accessToken);
|
||||
// const hasAccess = accessObject.permissions?.some(
|
||||
// (p: any) => p.method === method && p.url === path,
|
||||
@@ -49,7 +32,7 @@ export class EndpointControlGuard implements CanActivate {
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
const selectToken = getSelectTokenFromHeader(req);
|
||||
const selectToken = this.cacheService.mergeSelectKey(req);
|
||||
const method = req.method;
|
||||
const path = req.route?.path;
|
||||
console.log('EndpointControlGuard', selectToken, method, path);
|
||||
|
||||
@@ -18,7 +18,6 @@ class PasswordHandlers {
|
||||
|
||||
create_hashed_password(uuid: string, password: string): string {
|
||||
const data = `${uuid}:${password}`;
|
||||
console.log(crypto.createHash('sha256').update(data).digest('hex'));
|
||||
return crypto.createHash('sha256').update(data).digest('hex');
|
||||
}
|
||||
|
||||
@@ -33,7 +32,6 @@ class PasswordHandlers {
|
||||
hashed_password: string,
|
||||
): boolean {
|
||||
const created_hashed_password = this.create_hashed_password(uuid, password);
|
||||
console.log('created_hashed_password', created_hashed_password);
|
||||
return created_hashed_password === hashed_password;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,17 @@ import {
|
||||
import { CacheService } from '@/src/cache.service';
|
||||
import { users } from '@prisma/client';
|
||||
import { PasswordHandlers } from './login_handler';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, ForbiddenException } from '@nestjs/common';
|
||||
|
||||
interface LoginFromRedis {
|
||||
key: string;
|
||||
value: AuthToken;
|
||||
}
|
||||
|
||||
interface SelectFromRedis {
|
||||
key: string;
|
||||
value: TokenDictInterface;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class RedisHandlers {
|
||||
@@ -17,6 +27,50 @@ export class RedisHandlers {
|
||||
private readonly passwordService: PasswordHandlers,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates that a Redis key follows the expected format
|
||||
* Format: AUTH_TOKEN:token:token:UUID or AUTH_TOKEN:token:token:*:*
|
||||
this.AUTH_TOKEN:token:token:UUID:UUID
|
||||
*/
|
||||
private validateRedisKey(redisKey: string): boolean {
|
||||
if (!redisKey.startsWith(this.AUTH_TOKEN + ':')) {
|
||||
throw new ForbiddenException(
|
||||
`Invalid Redis key format. Must start with ${this.AUTH_TOKEN}:`,
|
||||
);
|
||||
}
|
||||
const colonCount = (redisKey.match(/:/g) || []).length;
|
||||
if (colonCount !== 4) {
|
||||
throw new ForbiddenException(
|
||||
`Invalid Redis key format. Must have exactly 5 colons. Found: ${colonCount}`,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public mergeLoginKey(req: Request): string {
|
||||
const acsToken = req.headers['acs'];
|
||||
if (!acsToken) {
|
||||
throw new ForbiddenException('Access token header is missing');
|
||||
}
|
||||
const mergedRedisKey = `${this.AUTH_TOKEN}:${acsToken}:${acsToken}:*:*`;
|
||||
this.validateRedisKey(mergedRedisKey);
|
||||
return mergedRedisKey;
|
||||
}
|
||||
|
||||
public mergeSelectKey(req: Request): string {
|
||||
const acsToken = req.headers['acs'];
|
||||
if (!acsToken) {
|
||||
throw new ForbiddenException('Access token header is missing');
|
||||
}
|
||||
const slcToken = req.headers['slc'];
|
||||
if (!slcToken) {
|
||||
throw new ForbiddenException('Select token header is missing');
|
||||
}
|
||||
const mergedRedisKey = `${this.AUTH_TOKEN}:${acsToken}:${slcToken}:*:*`;
|
||||
this.validateRedisKey(mergedRedisKey);
|
||||
return mergedRedisKey;
|
||||
}
|
||||
|
||||
generateSelectToken(accessToken: string, userUUID: string) {
|
||||
return this.passwordService.createSelectToken(accessToken, userUUID);
|
||||
}
|
||||
@@ -25,22 +79,97 @@ export class RedisHandlers {
|
||||
return this.passwordService.generateAccessToken();
|
||||
}
|
||||
|
||||
async getLoginFromRedis(redisKey: string): Promise<AuthToken> {
|
||||
return this.cacheService.get(redisKey);
|
||||
private async scanKeys(pattern: string): Promise<string[]> {
|
||||
this.validateRedisKey(pattern);
|
||||
const client = (this.cacheService as any).client;
|
||||
if (!client) throw new Error('Redis client not available');
|
||||
|
||||
const keys: string[] = [];
|
||||
let cursor = '0';
|
||||
|
||||
do {
|
||||
const [nextCursor, matchedKeys] = await client.scan(
|
||||
cursor,
|
||||
'MATCH',
|
||||
pattern,
|
||||
);
|
||||
cursor = nextCursor;
|
||||
keys.push(...matchedKeys);
|
||||
} while (cursor !== '0');
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
async getSelectFromRedis(redisKey: string): Promise<TokenDictInterface> {
|
||||
return this.cacheService.get(redisKey);
|
||||
async getLoginFromRedis(req: Request): Promise<LoginFromRedis | null> {
|
||||
const mergedKey = this.mergeLoginKey(req);
|
||||
if (mergedKey.includes('*')) {
|
||||
const keys = await this.scanKeys(mergedKey);
|
||||
if (keys.length === 0) {
|
||||
throw new ForbiddenException('Authorization failed - No matching keys');
|
||||
}
|
||||
for (const key of keys) {
|
||||
const parts = key.split(':');
|
||||
if (parts.length >= 3) {
|
||||
if (parts[1] === parts[2]) {
|
||||
const value = await this.cacheService.get(key);
|
||||
if (value) {
|
||||
return { key, value };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ForbiddenException('Authorization failed - No valid keys');
|
||||
}
|
||||
|
||||
const value = await this.cacheService.get(mergedKey);
|
||||
return value ? { key: mergedKey, value } : null;
|
||||
}
|
||||
|
||||
async renewTtlLoginFromRedis(redisKey: string): Promise<any> {
|
||||
const token = await this.getLoginFromRedis(redisKey);
|
||||
return this.cacheService.set_with_ttl(redisKey, token, 60 * 30);
|
||||
async getSelectFromRedis(req: Request): Promise<SelectFromRedis | null> {
|
||||
const mergedKey = this.mergeSelectKey(req);
|
||||
if (mergedKey.includes('*')) {
|
||||
const keys = await this.scanKeys(mergedKey);
|
||||
|
||||
if (keys.length === 0) {
|
||||
throw new ForbiddenException(
|
||||
'Authorization failed - No matching select keys',
|
||||
);
|
||||
}
|
||||
for (const key of keys) {
|
||||
const value = await this.cacheService.get(key);
|
||||
if (value) {
|
||||
return { key, value };
|
||||
}
|
||||
}
|
||||
throw new ForbiddenException(
|
||||
'Authorization failed - No valid select keys',
|
||||
);
|
||||
}
|
||||
|
||||
const value = await this.cacheService.get(mergedKey);
|
||||
return value ? { key: mergedKey, value } : null;
|
||||
}
|
||||
|
||||
async renewTtlSelectFromRedis(redisKey: string): Promise<any> {
|
||||
const token = await this.getSelectFromRedis(redisKey);
|
||||
return this.cacheService.set_with_ttl(redisKey, token, 60 * 30);
|
||||
async deleteLoginFromRedis(req: Request): Promise<any> {
|
||||
const mergedKey = this.mergeLoginKey(req);
|
||||
return this.cacheService.delete(mergedKey);
|
||||
}
|
||||
|
||||
async deleteSelectFromRedis(req: Request): Promise<any> {
|
||||
const mergedKey = this.mergeSelectKey(req);
|
||||
return this.cacheService.delete(mergedKey);
|
||||
}
|
||||
|
||||
async renewTtlLoginFromRedis(req: Request): Promise<any> {
|
||||
const mergedKey = this.mergeLoginKey(req);
|
||||
const value = await this.cacheService.get(mergedKey);
|
||||
return this.cacheService.set_with_ttl(mergedKey, value, 86400);
|
||||
}
|
||||
|
||||
async renewTtlSelectFromRedis(req: Request): Promise<any> {
|
||||
const mergedKey = this.mergeSelectKey(req);
|
||||
const value = await this.cacheService.get(mergedKey);
|
||||
return this.cacheService.set_with_ttl(mergedKey, value, 60 * 30);
|
||||
}
|
||||
|
||||
async setLoginToRedis(token: AuthToken, userUUID: string): Promise<any> {
|
||||
|
||||
Reference in New Issue
Block a user