- Introduced new columns `status`, `created_by`, and `updated_by` in the `users` table to track user status and ownership. - Updated the `employees` table to include a foreign key reference to the `users` table via `user_id`. - Created migration script `0012_users_primary.sql` to apply these changes to the database schema. - Enhanced the `EmployeesService` and `EmployeesRepository` to support user assignments and related data retrieval. - Updated DTOs and service methods to reflect the new user and employee relationships. - Added unit tests to validate the new functionality and ensure data integrity. - Modified existing controllers to accommodate the new fields and relationships in user and employee management.
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { PassportStrategy } from '@nestjs/passport';
|
|
import { ExtractJwt, Strategy } from 'passport-jwt';
|
|
import type {
|
|
AuthUser,
|
|
JwtAccessPayload,
|
|
} from '../../../common/auth/auth-user';
|
|
import { UsersService } from '../../users/users.service';
|
|
import { RevokedAccessTokensRepository } from '../revoked-access-tokens.repository';
|
|
|
|
@Injectable()
|
|
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
|
constructor(
|
|
config: ConfigService,
|
|
private readonly usersService: UsersService,
|
|
private readonly revokedAccessTokensRepository: RevokedAccessTokensRepository,
|
|
) {
|
|
super({
|
|
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
ignoreExpiration: false,
|
|
secretOrKey: config.getOrThrow<string>('JWT_ACCESS_SECRET'),
|
|
algorithms: ['HS256'],
|
|
});
|
|
}
|
|
|
|
async validate(payload: JwtAccessPayload): Promise<AuthUser> {
|
|
if (payload.typ !== 'access' || !payload.sub || !payload.jti) {
|
|
throw new UnauthorizedException('Invalid access token');
|
|
}
|
|
|
|
const revoked = await this.revokedAccessTokensRepository.exists(
|
|
payload.jti,
|
|
);
|
|
if (revoked) {
|
|
throw new UnauthorizedException('Access token revoked');
|
|
}
|
|
|
|
const user = await this.usersService.findById(payload.sub);
|
|
if (!user) {
|
|
throw new UnauthorizedException('User not found');
|
|
}
|
|
this.usersService.assertCanAuthenticate(user);
|
|
|
|
return {
|
|
id: user.id,
|
|
username: user.username,
|
|
jti: payload.jti,
|
|
isSuperadmin: user.isSuperadmin,
|
|
};
|
|
}
|
|
}
|