Как удалить сессию с JWT токеном?

В общем у меня есть вем приложение в котором есть users удалять из с БД mysql я не могу так на них много чего подвязано, я просто делаю деактивацию их прописываю в бд isActive = 0 (деактивирован) и isActive = 1 (это активный юзер). Как сделать так что б когда я деактивирую юзера я так же деактивировал его сессию, потому что пока он не нажмет logout он может находится на сайте.

вот собственно middelware

export const checkAuth = async (action: Action, roles: string[]) :Promise<boolean> => {
    let authHeader = action.request.headers.authorization;
    if (authHeader && action.request['_query'] && action.request['_query']['Authorization']) {
        authHeader = action.request['_query']['Authorization'];
    }

    if (authHeader) {
        const token = authHeader.split(' ')[1]
        return new Promise((resolve) => {
            jwt.verify(token, process.env.jwtSecret, (err: any, data: any) => {
                if (err) {
                    return resolve(false)
                }
                if (data.auth.userRole) {
                    if (!roles.length) {
                        if([22, 7].includes(data.auth.userId)) {
                            return resolve(false)
                        }
                        action.request.session = {}
                        action.request.session.auth = data.auth
                        return resolve(true)
                    }
                    if(roles.find(role => data.auth.userRole.indexOf(role) !== -1)) {
                        if([22, 7].includes(data.auth.userId)) {
                            return resolve(false)
                        }
                        action.request.session = {}
                        action.request.session.auth = data.auth;
                        return resolve(true);
                    }
                }
                if([22, 7].includes(data.auth.userId)) {
                    return resolve(false)
                }
            })
        })
    }
    return false;
};

тут я просто использовал костыль временный и исключил юзеров данным выражением по ид if([22, 7].includes(data.auth.userId))

Вот мой сервис, в нем я пытался записывать в БД токен и при обновлении юзера isActive = 0 записывать в БД пустой токен и возрващать его

@Service()
export class UserService {

    @OrmRepository()
    protected crmUserRepository: CrmUserRepository;

    async getAuthDataByGoogle(data: any) {
        let authData = {
            userId: 0,
            userEmail: '',
            userRole: '',
            jwtToken: '',
            expireIn: ''
        }
        const crmUser: CrmUser = await this.crmUserRepository.getUserByEmail(data);
        if (!crmUser || !crmUser.isActive) {
            throw new HttpError( 403, "Not found this google user in CRM-panel !");
        }
        try {
            authData.userId = crmUser.id;
            authData.userEmail = crmUser.name;
            authData.userRole = crmUser.role;
            authData.expireIn = crmUser.expiresIn
            authData.jwtToken = await this.generateToken(authData);
        } catch (e) {
            throw new HttpError(503, 'Sorry, there are some problems with mySql server. Try again later...')
        }
        return authData
    }

    async getAuthDataByLogin(data: any): Promise<AuthData> {
        let authData = {
            userId: 0,
            userEmail: '',
            userRole: '',
            jwtToken: '',
            expireIn: ''
        }
        await this.hashPassword(data);
        const crmUser: CrmUser = await this.crmUserRepository.getUserForLogin(data);
        if (!crmUser || !crmUser.isActive) {
            throw new HttpError( 403, "Access Denied!");
        }
        try {
            authData.userId = crmUser.id;
            authData.userEmail = crmUser.name;
            authData.expireIn = crmUser.expiresIn;
            authData.userRole = crmUser.role;
            authData.jwtToken = await this.generateToken(authData);
        } catch (e) {
            throw new HttpError(503, 'Sorry, there are some problems with mySql server. Try again later...')
        }
        return authData
    }

    async generateToken (authData: any) {
        const token = jwt.sign(
            {auth: authData},
            process.env.jwtSecret,
            {
                expiresIn: authData.expireIn,
            }
        );

        await this.crmUserRepository.updateToken(authData.userId, token);

        return token;
    }


    async deactivateUser(userId: number) {
        await this.crmUserRepository.updateToken(userId, '');
    }


    async hashPassword(user: CrmUser) {
        user.password = crypto.createHash('md5').update(user.password).digest("hex");
    }
}

export interface AuthData {
    userId: number;
    userRole: string;
    userEmail: string;
    jwtToken: string;
    expireIn: string;
}

export interface UserSession extends Express.Session {
    auth?: AuthData
}

вот репозиторий обновление токена

async updateToken(userId: number, token: string | null) {
    await this.createQueryBuilder()
        .update(CrmUser)
        .set({ token: token || '' })
        .where("id = :userId", { userId: userId })
        .execute();
}

вот сам Entity в которых указана таблицца и ее колонки

@Entity('crmUsers', { schema: process.env.mysqlName })
export class CrmUser {
    @PrimaryGeneratedColumn({ type: "int", name: "id" })
    id: number;

    @Column("varchar", { name: "name", length: 255 })
    name: string;

    @Column("varchar", { name: "password", length: 255 })
    password: string;

    @Column("enum", {
        name: "role",
        enum: ["ADMIN", "USER", "FINANCE"],
        default: "USER",
    })
    role: "ADMIN" | "USER" | "FINANCE";

    @Column('varchar', {
        name: 'expiresIn',
        length: 255,
        nullable: false,
        default: () => '1h'
    })
    expiresIn: string;

    @Column('int', {
        name: 'isActive',
        nullable: false,
        default: '1'
    })
    isActive: number;

    @Column("varchar", {
        name: "token",
        length: 255,
        default: '' })
    token: string;

    @OneToMany(() => UserLogs, (userLogs) => userLogs.userId)
    userLogs: UserLogs[];

    @OneToMany(() => FinanceLogs, (financeLogs) => financeLogs.user)
    financeLogs: FinanceLogs[];
}

ну вот вот сам контроллер

@Authorized()
@JsonController('/users')
export class UsersController extends AbstractController{

    @OrmRepository()
    protected repository: CrmUserRepository;

    @Inject()
    private userService: UserService;


    private loggerData: any;


    @Get()
    async getAllUsers(@Req() req: Request, @Res() res: Response) {
        return await this.repository.find({ isActive: Equal(1), });
    }

    @Post()
    async createUser(@Req() req: Request, @Res() res: Response) {

        const user = Object.assign(new CrmUser(), req.body)
        try {
            const candidate = await this.repository.getUserByEmail(user)
            if (candidate) {
                return res.status(400).send({data: 'The email has already existed.'});
            } else {
                await this.userService.hashPassword(user)
                await this.repository.save(user);
                await this.userLoggingService.AfterInsert(req.session, user);
                return res.status(200).send({data: `User has been saved !`})
            }
        } catch (e) {
            console.log(e)
            const msg: string = `Server error. Please try later.`
            this.TelegramBot.sendMessage(process.env.alertChartId, msg)
                .catch( (err: Error) => {
                    console.error(`Bot error:\n"${err}"`)
                });
            return res.status(e.httpCode).send({data: msg})
        }
    }

    @Put('/:id')
    async updateUser(@Req() req: Request, @Res() res: Response) {
        const id = +req.params.id;
        const data = req.body;
        let entity: any;
        try {
            entity = await this.repository.findOne({where: {id: id}});
            if (entity.name !== data.name) {
                const candidate = await this.repository.getUserByEmail(data)
                if (candidate) {
                    return res.status(400).send({data: 'The email has already existed.'})
                }
            }
            if (data && data.password) {
                await this.userService.hashPassword(data);
            }
            const result = {...entity, ...data}
            console.log(data.auth)
            await this.repository.save(result);
            await this.userService.deactivateUser(id)
            await this.userLoggingService.AfterUpdate(req.session, entity, result)
        } catch (e) {
            return res.status(404).send({data: 'Server has problem. Please try again later.'})
        }
        return res.status(200).send({data: 'User has been saved !'})
    }
}

Что не так я делаю и как будет правильно это сделать ?


Ответы (0 шт):