Initial commit: Meshkee CMS API
NestJS backend with Prisma, Docker Compose for Postgres/Redis, and deploy docs for the production VM.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
import {
|
||||
AuthJwtPayload,
|
||||
AuthUser,
|
||||
DashboardType,
|
||||
} from '../auth.types';
|
||||
import { PermissionsService } from '../permissions.service';
|
||||
import { parseUserProfile } from '../profile.util';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
config: ConfigService,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly permissions: PermissionsService,
|
||||
) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: config.getOrThrow<string>('JWT_ACCESS_SECRET'),
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: AuthJwtPayload): Promise<AuthUser> {
|
||||
if (payload.type !== 'access') {
|
||||
throw new UnauthorizedException('Invalid token type');
|
||||
}
|
||||
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: BigInt(payload.sub) },
|
||||
include: {
|
||||
userRoles: { include: { role: true } },
|
||||
businessCustomers: { include: { business: true } },
|
||||
},
|
||||
});
|
||||
|
||||
if (!user || !user.isActive) {
|
||||
throw new UnauthorizedException('User not found or inactive');
|
||||
}
|
||||
|
||||
const roles = user.userRoles.map((ur) => ur.role.slug);
|
||||
const businesses = await this.permissions.getBusinessMemberships(user.id);
|
||||
const customerBusinesses = user.businessCustomers.map((bc) => ({
|
||||
id: bc.business.id,
|
||||
name: bc.business.name,
|
||||
slug: bc.business.slug,
|
||||
}));
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
cellNumber: user.cellNumber,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
cellVerifiedAt: user.cellVerifiedAt,
|
||||
roles,
|
||||
dashboard: this.resolveDashboard(roles, businesses.length),
|
||||
profile: parseUserProfile(user.profile),
|
||||
businesses,
|
||||
customerBusinesses,
|
||||
};
|
||||
}
|
||||
|
||||
private resolveDashboard(roles: string[], businessCount: number): DashboardType {
|
||||
if (roles.includes('super_admin')) {
|
||||
return 'super_admin';
|
||||
}
|
||||
if (
|
||||
roles.includes('business_owner') ||
|
||||
roles.includes('business_staff') ||
|
||||
roles.includes('owner') ||
|
||||
businessCount > 0
|
||||
) {
|
||||
return 'business';
|
||||
}
|
||||
return 'customer';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user