lint and format

This commit is contained in:
Kartik Datrika
2026-03-23 15:46:32 +05:30
parent 30a4cda178
commit a1157ab4c1
48 changed files with 10980 additions and 2810 deletions

View File

@@ -5,28 +5,32 @@ import { OzonetelAgentService } from '../ozonetel/ozonetel-agent.service';
@Controller('auth')
export class AuthController {
private readonly logger = new Logger(AuthController.name);
private readonly graphqlUrl: string;
private readonly workspaceSubdomain: string;
private readonly origin: string;
private readonly logger = new Logger(AuthController.name);
private readonly graphqlUrl: string;
private readonly workspaceSubdomain: string;
private readonly origin: string;
constructor(
private config: ConfigService,
private ozonetelAgent: OzonetelAgentService,
) {
this.graphqlUrl = config.get<string>('platform.graphqlUrl')!;
this.workspaceSubdomain = process.env.PLATFORM_WORKSPACE_SUBDOMAIN ?? 'fortytwo-dev';
this.origin = process.env.PLATFORM_ORIGIN ?? 'http://fortytwo-dev.localhost:4010';
}
constructor(
private config: ConfigService,
private ozonetelAgent: OzonetelAgentService,
) {
this.graphqlUrl = config.get<string>('platform.graphqlUrl')!;
this.workspaceSubdomain =
process.env.PLATFORM_WORKSPACE_SUBDOMAIN ?? 'fortytwo-dev';
this.origin =
process.env.PLATFORM_ORIGIN ?? 'http://fortytwo-dev.localhost:4010';
}
@Post('login')
async login(@Body() body: { email: string; password: string }) {
this.logger.log(`Login attempt for ${body.email}`);
@Post('login')
async login(@Body() body: { email: string; password: string }) {
this.logger.log(`Login attempt for ${body.email}`);
try {
// Step 1: Get login token
const loginRes = await axios.post(this.graphqlUrl, {
query: `mutation GetLoginToken($email: String!, $password: String!) {
try {
// Step 1: Get login token
const loginRes = await axios.post(
this.graphqlUrl,
{
query: `mutation GetLoginToken($email: String!, $password: String!) {
getLoginTokenFromCredentials(
email: $email
password: $password
@@ -35,26 +39,31 @@ export class AuthController {
loginToken { token }
}
}`,
variables: { email: body.email, password: body.password },
}, {
headers: {
'Content-Type': 'application/json',
'X-Workspace-Subdomain': this.workspaceSubdomain,
},
});
variables: { email: body.email, password: body.password },
},
{
headers: {
'Content-Type': 'application/json',
'X-Workspace-Subdomain': this.workspaceSubdomain,
},
},
);
if (loginRes.data.errors) {
throw new HttpException(
loginRes.data.errors[0]?.message ?? 'Login failed',
401,
);
}
if (loginRes.data.errors) {
throw new HttpException(
loginRes.data.errors[0]?.message ?? 'Login failed',
401,
);
}
const loginToken = loginRes.data.data.getLoginTokenFromCredentials.loginToken.token;
const loginToken =
loginRes.data.data.getLoginTokenFromCredentials.loginToken.token;
// Step 2: Exchange for access + refresh tokens
const tokenRes = await axios.post(this.graphqlUrl, {
query: `mutation GetAuthTokens($loginToken: String!) {
// Step 2: Exchange for access + refresh tokens
const tokenRes = await axios.post(
this.graphqlUrl,
{
query: `mutation GetAuthTokens($loginToken: String!) {
getAuthTokensFromLoginToken(
loginToken: $loginToken
origin: "${this.origin}"
@@ -65,99 +74,114 @@ export class AuthController {
}
}
}`,
variables: { loginToken },
}, {
headers: {
'Content-Type': 'application/json',
'X-Workspace-Subdomain': this.workspaceSubdomain,
},
});
variables: { loginToken },
},
{
headers: {
'Content-Type': 'application/json',
'X-Workspace-Subdomain': this.workspaceSubdomain,
},
},
);
if (tokenRes.data.errors) {
throw new HttpException(
tokenRes.data.errors[0]?.message ?? 'Token exchange failed',
401,
);
}
if (tokenRes.data.errors) {
throw new HttpException(
tokenRes.data.errors[0]?.message ?? 'Token exchange failed',
401,
);
}
const tokens = tokenRes.data.data.getAuthTokensFromLoginToken.tokens;
const accessToken = tokens.accessOrWorkspaceAgnosticToken.token;
const tokens = tokenRes.data.data.getAuthTokensFromLoginToken.tokens;
const accessToken = tokens.accessOrWorkspaceAgnosticToken.token;
// Step 3: Fetch user profile with roles
const profileRes = await axios.post(this.graphqlUrl, {
query: `{ currentUser { id email workspaceMember { id name { firstName lastName } userEmail avatarUrl roles { id label } } } }`,
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
});
// Step 3: Fetch user profile with roles
const profileRes = await axios.post(
this.graphqlUrl,
{
query: `{ currentUser { id email workspaceMember { id name { firstName lastName } userEmail avatarUrl roles { id label } } } }`,
},
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
},
);
const currentUser = profileRes.data?.data?.currentUser;
const workspaceMember = currentUser?.workspaceMember;
const roles = workspaceMember?.roles ?? [];
const roleLabels = roles.map((r: any) => r.label);
const currentUser = profileRes.data?.data?.currentUser;
const workspaceMember = currentUser?.workspaceMember;
const roles = workspaceMember?.roles ?? [];
const roleLabels = roles.map((r: any) => r.label);
// Determine app role from platform roles
let appRole = 'executive'; // default
if (roleLabels.includes('HelixEngage Manager')) {
appRole = 'admin';
} else if (roleLabels.includes('HelixEngage User')) {
// Distinguish CC agent from executive by email convention or config
// For now, emails containing 'cc' map to cc-agent
const email = workspaceMember?.userEmail ?? body.email;
appRole = email.includes('cc') ? 'cc-agent' : 'executive';
}
// Determine app role from platform roles
let appRole = 'executive'; // default
if (roleLabels.includes('HelixEngage Manager')) {
appRole = 'admin';
} else if (roleLabels.includes('HelixEngage User')) {
// Distinguish CC agent from executive by email convention or config
// For now, emails containing 'cc' map to cc-agent
const email = workspaceMember?.userEmail ?? body.email;
appRole = email.includes('cc') ? 'cc-agent' : 'executive';
}
this.logger.log(`User ${body.email} logged in with role: ${appRole} (platform roles: ${roleLabels.join(', ')})`);
this.logger.log(
`User ${body.email} logged in with role: ${appRole} (platform roles: ${roleLabels.join(', ')})`,
);
// Auto-login Ozonetel agent for CC agents (fire and forget)
if (appRole === 'cc-agent') {
const ozAgentId = process.env.OZONETEL_AGENT_ID ?? 'agent3';
const ozAgentPassword = process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$';
const ozSipId = process.env.OZONETEL_SIP_ID ?? '521814';
// Auto-login Ozonetel agent for CC agents (fire and forget)
if (appRole === 'cc-agent') {
const ozAgentId = process.env.OZONETEL_AGENT_ID ?? 'agent3';
const ozAgentPassword =
process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$';
const ozSipId = process.env.OZONETEL_SIP_ID ?? '521814';
this.ozonetelAgent.loginAgent({
agentId: ozAgentId,
password: ozAgentPassword,
phoneNumber: ozSipId,
mode: 'blended',
}).catch(err => {
this.logger.warn(`Ozonetel agent login failed (non-blocking): ${err.message}`);
});
}
this.ozonetelAgent
.loginAgent({
agentId: ozAgentId,
password: ozAgentPassword,
phoneNumber: ozSipId,
mode: 'blended',
})
.catch((err) => {
this.logger.warn(
`Ozonetel agent login failed (non-blocking): ${err.message}`,
);
});
}
return {
accessToken,
refreshToken: tokens.refreshToken.token,
user: {
id: currentUser?.id,
email: currentUser?.email,
firstName: workspaceMember?.name?.firstName ?? '',
lastName: workspaceMember?.name?.lastName ?? '',
avatarUrl: workspaceMember?.avatarUrl,
role: appRole,
platformRoles: roleLabels,
},
};
} catch (error) {
if (error instanceof HttpException) throw error;
this.logger.error(`Login proxy failed: ${error}`);
throw new HttpException('Authentication service unavailable', 503);
}
return {
accessToken,
refreshToken: tokens.refreshToken.token,
user: {
id: currentUser?.id,
email: currentUser?.email,
firstName: workspaceMember?.name?.firstName ?? '',
lastName: workspaceMember?.name?.lastName ?? '',
avatarUrl: workspaceMember?.avatarUrl,
role: appRole,
platformRoles: roleLabels,
},
};
} catch (error) {
if (error instanceof HttpException) throw error;
this.logger.error(`Login proxy failed: ${error}`);
throw new HttpException('Authentication service unavailable', 503);
}
}
@Post('refresh')
async refresh(@Body() body: { refreshToken: string }) {
if (!body.refreshToken) {
throw new HttpException('refreshToken required', 400);
}
@Post('refresh')
async refresh(@Body() body: { refreshToken: string }) {
if (!body.refreshToken) {
throw new HttpException('refreshToken required', 400);
}
this.logger.log('Token refresh request');
this.logger.log('Token refresh request');
try {
const res = await axios.post(this.graphqlUrl, {
query: `mutation RefreshToken($token: String!) {
try {
const res = await axios.post(
this.graphqlUrl,
{
query: `mutation RefreshToken($token: String!) {
renewToken(appToken: $token) {
tokens {
accessOrWorkspaceAgnosticToken { token expiresAt }
@@ -165,25 +189,29 @@ export class AuthController {
}
}
}`,
variables: { token: body.refreshToken },
}, {
headers: { 'Content-Type': 'application/json' },
});
variables: { token: body.refreshToken },
},
{
headers: { 'Content-Type': 'application/json' },
},
);
if (res.data.errors) {
this.logger.warn(`Token refresh failed: ${res.data.errors[0]?.message}`);
throw new HttpException('Token refresh failed', 401);
}
if (res.data.errors) {
this.logger.warn(
`Token refresh failed: ${res.data.errors[0]?.message}`,
);
throw new HttpException('Token refresh failed', 401);
}
const tokens = res.data.data.renewToken.tokens;
return {
accessToken: tokens.accessOrWorkspaceAgnosticToken.token,
refreshToken: tokens.refreshToken.token,
};
} catch (error) {
if (error instanceof HttpException) throw error;
this.logger.error(`Token refresh failed: ${error}`);
throw new HttpException('Token refresh failed', 401);
}
const tokens = res.data.data.renewToken.tokens;
return {
accessToken: tokens.accessOrWorkspaceAgnosticToken.token,
refreshToken: tokens.refreshToken.token,
};
} catch (error) {
if (error instanceof HttpException) throw error;
this.logger.error(`Token refresh failed: ${error}`);
throw new HttpException('Token refresh failed', 401);
}
}
}