Spaces:
Runtime error
Runtime error
File size: 5,334 Bytes
97dab2a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
// auth.controller.ts
import { Controller, Get, Req, Res } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UserSessionService } from '../user-session/user-session.service';
import { Request, Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';
import axios from 'axios';
@Controller('auth')
export class AuthController {
constructor(private readonly AuthService: AuthService,
private readonly UserSessionService: UserSessionService
) {}
@Get('login')
async login(@Res() res: Response) {
const authCodeUrlParameters = {
scopes: ['openid', 'profile', 'email'],
redirectUri: process.env.AUTH_REDIRCET_URL || '',
};
const client = this.AuthService.getClient();
const authCodeUrl = await client.getAuthCodeUrl(authCodeUrlParameters);
res.redirect(authCodeUrl);
}
@Get('redirect')
async redirect(@Req() req: Request, @Res() res: Response) {
const isProduction = process.env.NODE_ENV === 'production';
const tokenRequest = {
code: req.query.code as string,
scopes: ['openid', 'profile', 'email'],
redirectUri: process.env.AUTH_REDIRCET_URL || '',
};
const client = this.AuthService.getClient();
const authResponse = await client.acquireTokenByCode(tokenRequest);
if (!authResponse) {
return res.status(500).send('Authentication failed');
}
else {
if (authResponse) {
this.UserSessionService.setUser(res, authResponse.account);
}
if (authResponse.account) {
this.UserSessionService.setUserName(res, authResponse.account.name);
}
if (authResponse.accessToken) {
this.UserSessionService.setAccessToken(res, authResponse.accessToken);
}
// Add roles and userId to cookies if available
if (authResponse.account && authResponse.account.idTokenClaims) {
const roles = authResponse.account.idTokenClaims.roles || [];
const userId = authResponse.account.idTokenClaims.oid || authResponse.account.idTokenClaims.sub;
this.UserSessionService.setRoles(res, roles);
this.UserSessionService.setUserId(res, userId);
}
res.clearCookie('activeNavItem');
res.redirect('/auth/profile');
}
}
private async downloadUserPhoto(accessToken: string, userId: string): Promise<string> {
try {
const outputPath = path.join(process.cwd(), '/public/photos/'); // Output directory
// Ensure the output directory exists
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath, { recursive: true });
}
// Define the photo file path
const photoPath = path.join(outputPath, `${userId}.jpg`);
if (fs.existsSync(photoPath)) {
return `/photos/${userId}.jpg`;
}
// Fetch the user's photo using Axios
const response = await axios.get(`https://graph.microsoft.com/v1.0/users/${userId}/photo/$value`, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'image/jpeg',
},
responseType: 'arraybuffer', // Important to get the binary data
});
// Write the photo to a local file
fs.writeFileSync(photoPath, response.data);
// Return the relative image URL for use in the frontend
return `/photos/${userId}.jpg`;
} catch (error) {
if (error.response && error.response.status === 404) {
// Handle the case where the photo is not found
console.log('User photo not found.');
return '/images/profile.jpg'; // Return a placeholder image URL
} else {
// Re-throw the error if it's not a 404
throw error;
}
}
}
@Get('profile')
async profile(@Req() req: Request, @Res() res: Response) {
const user = req.cookies.user ? JSON.parse(req.cookies.user) : null;
const userName = req.cookies.userName;
const roles = req.cookies.roles;
const userId = req.cookies.userId;
const accessToken = req.cookies.accessToken;
console.log('dowloading profile');
// Check if the user cookie exists
if (!user) {
return res.status(401).send('Unauthorized: User not logged in.');
}
// Parse roles safely
const parsedRoles = roles ? JSON.parse(roles) : [];
try {
await this.downloadUserPhoto(accessToken,userId);
}catch (err) {
console.log('Photo not found: ' + err);
}
// Render the profile page with user information
return res.render('auth/profile', {
user: user,
userName: userName || 'Unknown User',
roles: parsedRoles,
userId: userId || 'Unknown User ID',
});
}
@Get('logout')
async logout(@Req() req: Request, @Res() res: Response) {
const protocol = req.protocol; // 'http' or 'https'
const host = req.get('host'); // 'localhost:3000' or 'example.com'
const baseUrl = `${protocol}://${host}`;
// Clear the user cookie
// res.clearCookie('user');
// res.clearCookie('userName');
// res.clearCookie('roles');
// res.clearCookie('userId');
// res.clearCookie('accessToken');
this.UserSessionService.clear(res);
res.redirect(`https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}/oauth2/v2.0/logout?post_logout_redirect_uri=${baseUrl}`);
}
}
|