managarten/apps-archived/mail/apps/backend/src/oauth/oauth.controller.ts
Till-JS ace7fa8f7f chore: archive finance, mail, moodlit apps and rename voxel-lava
- Move finance, mail, moodlit to apps-archived for later development
- Rename games/voxel-lava to games/voxelava

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 13:13:15 +01:00

150 lines
4.4 KiB
TypeScript

import { Controller, Get, Post, Query, Res, UseGuards, BadRequestException } from '@nestjs/common';
import { Response } from 'express';
import { JwtAuthGuard, CurrentUser, CurrentUserData } from '@manacore/shared-nestjs-auth';
import { GoogleOAuthService } from './google-oauth.service';
import { MicrosoftOAuthService } from './microsoft-oauth.service';
import { AccountService } from '../account/account.service';
@Controller('oauth')
export class OAuthController {
constructor(
private readonly googleOAuthService: GoogleOAuthService,
private readonly microsoftOAuthService: MicrosoftOAuthService,
private readonly accountService: AccountService
) {}
// ==================== Google OAuth ====================
@Post('google/init')
@UseGuards(JwtAuthGuard)
async initGoogleOAuth(@CurrentUser() user: CurrentUserData) {
if (!this.googleOAuthService.isConfigured()) {
throw new BadRequestException(
'Google OAuth is not configured. Please set GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI.'
);
}
const authUrl = this.googleOAuthService.getAuthUrl(user.userId);
return { authUrl };
}
@Get('google/callback')
async googleCallback(
@Query('code') code: string,
@Query('state') state: string,
@Query('error') error: string,
@Res() res: Response
) {
// Redirect URL for the frontend
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5186';
if (error) {
return res.redirect(`${frontendUrl}/accounts?error=${encodeURIComponent(error)}`);
}
if (!code || !state) {
return res.redirect(`${frontendUrl}/accounts?error=missing_params`);
}
try {
const { userId, tokens, userInfo } = await this.googleOAuthService.handleCallback(
code,
state
);
// Create the email account
await this.accountService.create({
userId,
name: userInfo.name || userInfo.email,
email: userInfo.email,
provider: 'gmail',
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
tokenExpiresAt: tokens.expiresAt,
tokenScopes: tokens.scopes,
syncEnabled: true,
});
return res.redirect(`${frontendUrl}/accounts?success=gmail_connected`);
} catch (err) {
const message = err instanceof Error ? err.message : 'Unknown error';
return res.redirect(`${frontendUrl}/accounts?error=${encodeURIComponent(message)}`);
}
}
// ==================== Microsoft OAuth ====================
@Post('microsoft/init')
@UseGuards(JwtAuthGuard)
async initMicrosoftOAuth(@CurrentUser() user: CurrentUserData) {
if (!this.microsoftOAuthService.isConfigured()) {
throw new BadRequestException(
'Microsoft OAuth is not configured. Please set MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, and MICROSOFT_REDIRECT_URI.'
);
}
const authUrl = this.microsoftOAuthService.getAuthUrl(user.userId);
return { authUrl };
}
@Get('microsoft/callback')
async microsoftCallback(
@Query('code') code: string,
@Query('state') state: string,
@Query('error') error: string,
@Query('error_description') errorDescription: string,
@Res() res: Response
) {
// Redirect URL for the frontend
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5186';
if (error) {
const message = errorDescription || error;
return res.redirect(`${frontendUrl}/accounts?error=${encodeURIComponent(message)}`);
}
if (!code || !state) {
return res.redirect(`${frontendUrl}/accounts?error=missing_params`);
}
try {
const { userId, tokens, userInfo } = await this.microsoftOAuthService.handleCallback(
code,
state
);
// Create the email account
await this.accountService.create({
userId,
name: userInfo.name || userInfo.email,
email: userInfo.email,
provider: 'outlook',
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
tokenExpiresAt: tokens.expiresAt,
tokenScopes: tokens.scopes,
syncEnabled: true,
});
return res.redirect(`${frontendUrl}/accounts?success=outlook_connected`);
} catch (err) {
const message = err instanceof Error ? err.message : 'Unknown error';
return res.redirect(`${frontendUrl}/accounts?error=${encodeURIComponent(message)}`);
}
}
// ==================== Status ====================
@Get('status')
@UseGuards(JwtAuthGuard)
async getOAuthStatus() {
return {
google: {
configured: this.googleOAuthService.isConfigured(),
},
microsoft: {
configured: this.microsoftOAuthService.isConfigured(),
},
};
}
}