Как удалить сессию с 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 !'})
}
}
Что не так я делаю и как будет правильно это сделать ?