Skip to content

Commit

Permalink
fix: get only active employees
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-rocket committed Apr 30, 2024
1 parent 5ae6718 commit 49e78ca
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 83 deletions.
22 changes: 17 additions & 5 deletions packages/core/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,13 @@ export class AuthController {
@Post('/signin.email')
@Public()
@UseValidationPipe({ transform: true })
async sendWorkspaceSigninCode(@Body() entity: UserEmailDTO, @I18nLang() locale: LanguagesEnum): Promise<any> {
return await this.commandBus.execute(new WorkspaceSigninSendCodeCommand(entity, locale));
async sendWorkspaceSigninCode(
@Body() entity: UserEmailDTO,
@I18nLang() locale: LanguagesEnum
): Promise<any> {
return await this.commandBus.execute(
new WorkspaceSigninSendCodeCommand(entity, locale)
);
}

/**
Expand All @@ -190,7 +195,10 @@ export class AuthController {
@Query() query: Record<string, boolean>,
@Body() input: WorkspaceSigninEmailVerifyDTO
): Promise<IUserSigninWorkspaceResponse> {
return await this.authService.confirmWorkspaceSigninByCode(input, convertNativeParameters(query.includeTeams));
return await this.authService.confirmWorkspaceSigninByCode(
input,
convertNativeParameters(query.includeTeams)
);
}

/**
Expand All @@ -202,8 +210,12 @@ export class AuthController {
@Post('/signin.workspace')
@Public()
@UseValidationPipe({ whitelist: true })
async signinWorkspaceByToken(@Body() input: WorkspaceSigninDTO): Promise<IAuthResponse | null> {
return await this.commandBus.execute(new WorkspaceSigninVerifyTokenCommand(input));
async signinWorkspaceByToken(
@Body() input: WorkspaceSigninDTO
): Promise<IAuthResponse | null> {
return await this.commandBus.execute(
new WorkspaceSigninVerifyTokenCommand(input)
);
}

/**
Expand Down
99 changes: 46 additions & 53 deletions packages/core/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,14 @@ export class AuthService extends SocialAuthService {

/** Fetching users matching the query */
let users = await this.userService.find({
where: [
{
email,
isActive: true,
isArchived: false,
hash: Not(IsNull())
}
],
relations: {
tenant: true
},
order: {
createdAt: 'DESC'
}
where: [{
email,
isActive: true,
isArchived: false,
hash: Not(IsNull())
}],
relations: { tenant: true },
order: { createdAt: 'DESC' }
});

// Filter users based on password match
Expand All @@ -164,18 +158,15 @@ export class AuthService extends SocialAuthService {
// Update all users with a single query
const ids = users.map((user: IUser) => user.id);

await this.typeOrmUserRepository.update(
{
id: In(ids),
email,
isActive: true,
isArchived: false
},
{
code,
codeExpireAt
}
);
await this.typeOrmUserRepository.update({
id: In(ids),
email,
isActive: true,
isArchived: false
}, {
code,
codeExpireAt
});

// Determining the response based on the number of matching users
const response: IUserSigninWorkspaceResponse = await this.createUserSigninWorkspaceResponse({
Expand Down Expand Up @@ -653,9 +644,7 @@ export class AuthService extends SocialAuthService {
console.log('Get access token from refresh token');
try {
const user = RequestContext.currentUser();
return {
token: await this.getJwtAccessToken(user)
};
return { token: await this.getJwtAccessToken(user) };
} catch (error) {
console.log('Error while getting jwt access token from refresh token', error);
}
Expand Down Expand Up @@ -849,40 +838,44 @@ export class AuthService extends SocialAuthService {
isActive: true,
isArchived: false
},
relations: {
role: true
}
relations: { role: true }
});

await this.typeOrmUserRepository.update(
{
email,
id: userId,
tenantId,
code,
isActive: true
},
{
code: null,
codeExpireAt: null
}
);

const employee = await this.employeeService.findOneByOptions({
where: { userId: user.id }
await this.typeOrmUserRepository.update({
email,
id: userId,
tenantId,
code,
isActive: true,
isArchived: false
}, {
code: null,
codeExpireAt: null
});

// If employees are inactive
if (employee && (employee.isActive === false || employee.isArchived === true)) {
// Retrieve the employee details associated with the user.
const employee = await this.employeeService.findOneByUserId(user.id);

// Check if the employee is active and not archived. If not, throw an error.
if (employee && (!employee.isActive || employee.isArchived)) {
throw new UnauthorizedException();
}

const access_token = await this.getJwtAccessToken(user);
const refresh_token = await this.getJwtRefreshToken(user);
// Generate both access and refresh tokens concurrently for efficiency.
const [access_token, refresh_token] = await Promise.all([
this.getJwtAccessToken(user),
this.getJwtRefreshToken(user)
]);

// Store the current refresh token with the user for later validation.
await this.userService.setCurrentRefreshToken(refresh_token, user.id);

// Return the user object with user details, tokens, and optionally employee info if it exists.
return {
user,
user: {
...user,
...(employee && { employee })
},
token: access_token,
refresh_token: refresh_token
};
Expand Down
30 changes: 20 additions & 10 deletions packages/core/src/auth/strategies/jwt-refresh-token.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,32 @@ export class JwtRefreshTokenStrategy extends PassportStrategy(Strategy, 'jwt-ref
});
}

async validate(request: Request, payload: JwtPayload, done: Function) {
/**
* Validates the refresh token and payload to ensure user authorization.
*
* @param request - The incoming request, expected to contain the refresh token in its body.
* @param payload - The JWT payload to validate.
* @param done - The callback function to be called upon validation completion.
*/
async validate(
request: Request,
payload: JwtPayload,
done: Function
): Promise<void> {
try {
const { body } = request;
const refresh_token = body.refresh_token;
const { refresh_token } = request.body; // Extract the refresh token

// Validate the user using the refresh token and JWT payload
const user = await this.userService.getUserIfRefreshTokenMatches(refresh_token, payload);

if (!user) {
return done(new UnauthorizedException('unauthorized'), false);
} else {
done(null, user);
return done(new UnauthorizedException('Unauthorized'), false); // Return unauthorized if validation fails
}

done(null, user); // Return user if validation is successful
} catch (err) {
return done(
new UnauthorizedException('unauthorized', err.message),
false
);
// Handle errors and provide a meaningful response
return done(new UnauthorizedException('Unauthorized', err.message), false);
}
}
}
33 changes: 21 additions & 12 deletions packages/core/src/employee/employee.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ export class EmployeeService extends TenantAwareCrudService<Employee> {
// Get the tenant ID from the current request context
const tenantId = RequestContext.currentTenantId();

// Construct the where clause based on whether tenantId is available
const whereClause = tenantId ? { tenantId, userId: In(userIds) } : { userId: In(userIds) };
// Construct the base where clause for querying employees by user IDs
const whereClause = {
userId: In(userIds), // Find employees with matching user IDs
isActive: true, // Only active employees
isArchived: false, // Exclude archived employees
...(tenantId && { tenantId }), // Include tenant ID if available
};

// Execute the query based on the ORM type
switch (this.ormType) {
Expand Down Expand Up @@ -75,7 +80,12 @@ export class EmployeeService extends TenantAwareCrudService<Employee> {
try {
const tenantId = RequestContext.currentTenantId();
// Construct the where clause based on whether tenantId is available
const whereClause = tenantId ? { tenantId, userId } : { userId };
const whereClause = {
userId,
isActive: true,
isArchived: false,
...(tenantId && { tenantId }) // Include tenantId if available
};

switch (this.ormType) {
case MultiORMEnum.MikroORM: {
Expand Down Expand Up @@ -106,7 +116,12 @@ export class EmployeeService extends TenantAwareCrudService<Employee> {
const tenantId = RequestContext.currentTenantId();

// Construct the where clause based on whether tenantId is available
const whereClause = tenantId ? { tenantId, userId } : { userId };
const whereClause = {
userId,
isActive: true,
isArchived: false,
...(tenantId && { tenantId }) // Include tenantId if available
};
const queryOptions = options ? { ...options } : {};

switch (this.ormType) {
Expand Down Expand Up @@ -138,14 +153,8 @@ export class EmployeeService extends TenantAwareCrudService<Employee> {
public async findAllActive(): Promise<Employee[]> {
try {
return await super.find({
where: {
isActive: true,
isArchived: false,
},
relations: {
user: true,
organization: true
},
where: { isActive: true, isArchived: false, },
relations: { user: true, organization: true },
});
} catch (error) {
// Handle any potential errors, log, and optionally rethrow or return a default value.
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,7 @@ export class UserService extends TenantAwareCrudService<User> {
query.setFindOptions({
join: {
alias: 'user',
leftJoin: {
role: 'user.role'
}
leftJoin: { role: 'user.role' }
}
});
query.where((query: SelectQueryBuilder<User>) => {
Expand All @@ -416,6 +414,7 @@ export class UserService extends TenantAwareCrudService<User> {
});
const user = await query.getOneOrFail();
const isRefreshTokenMatching = await bcrypt.compare(refreshToken, user.refreshToken);

if (isRefreshTokenMatching) {
return user;
} else {
Expand Down

0 comments on commit 49e78ca

Please sign in to comment.