update 2
This commit is contained in:
@@ -1,12 +1,28 @@
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
// Build connection configuration from environment variables
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'db',
|
||||
port: process.env.DB_PORT || 5432,
|
||||
database: process.env.DB_NAME || 'turftracker',
|
||||
user: process.env.DB_USER || 'turftracker',
|
||||
password: process.env.DB_PASSWORD || 'password123',
|
||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
||||
max: 20,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
});
|
||||
};
|
||||
|
||||
// Fallback to DATABASE_URL if provided (for backwards compatibility)
|
||||
const pool = process.env.DATABASE_URL
|
||||
? new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
||||
max: 20,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
})
|
||||
: new Pool(dbConfig);
|
||||
|
||||
// Test the connection
|
||||
pool.on('connect', () => {
|
||||
|
||||
@@ -2,7 +2,7 @@ const express = require('express');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const passport = require('passport');
|
||||
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
||||
const OAuth2Strategy = require('passport-oauth2').Strategy;
|
||||
const pool = require('../config/database');
|
||||
const { validateRequest } = require('../utils/validation');
|
||||
const { registerSchema, loginSchema, changePasswordSchema } = require('../utils/validation');
|
||||
@@ -10,18 +10,30 @@ const { AppError } = require('../middleware/errorHandler');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Configure Google OAuth2 strategy
|
||||
if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
|
||||
passport.use(new GoogleStrategy({
|
||||
clientID: process.env.GOOGLE_CLIENT_ID,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
callbackURL: '/api/auth/google/callback'
|
||||
// Configure Authentik OAuth2 strategy
|
||||
if (process.env.AUTHENTIK_CLIENT_ID && process.env.AUTHENTIK_CLIENT_SECRET && process.env.AUTHENTIK_BASE_URL) {
|
||||
passport.use('authentik', new OAuth2Strategy({
|
||||
authorizationURL: `${process.env.AUTHENTIK_BASE_URL}/application/o/authorize/`,
|
||||
tokenURL: `${process.env.AUTHENTIK_BASE_URL}/application/o/token/`,
|
||||
clientID: process.env.AUTHENTIK_CLIENT_ID,
|
||||
clientSecret: process.env.AUTHENTIK_CLIENT_SECRET,
|
||||
callbackURL: process.env.AUTHENTIK_CALLBACK_URL || '/api/auth/authentik/callback'
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
try {
|
||||
// Get user info from Authentik
|
||||
const axios = require('axios');
|
||||
const userInfoResponse = await axios.get(`${process.env.AUTHENTIK_BASE_URL}/application/o/userinfo/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`
|
||||
}
|
||||
});
|
||||
|
||||
const userInfo = userInfoResponse.data;
|
||||
|
||||
// Check if user already exists
|
||||
const existingUser = await pool.query(
|
||||
'SELECT * FROM users WHERE oauth_provider = $1 AND oauth_id = $2',
|
||||
['google', profile.id]
|
||||
['authentik', userInfo.sub]
|
||||
);
|
||||
|
||||
if (existingUser.rows.length > 0) {
|
||||
@@ -31,14 +43,14 @@ if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
|
||||
// Check if user exists with same email
|
||||
const emailUser = await pool.query(
|
||||
'SELECT * FROM users WHERE email = $1',
|
||||
[profile.emails[0].value]
|
||||
[userInfo.email]
|
||||
);
|
||||
|
||||
if (emailUser.rows.length > 0) {
|
||||
// Link Google account to existing user
|
||||
// Link Authentik account to existing user
|
||||
await pool.query(
|
||||
'UPDATE users SET oauth_provider = $1, oauth_id = $2 WHERE id = $3',
|
||||
['google', profile.id, emailUser.rows[0].id]
|
||||
['authentik', userInfo.sub, emailUser.rows[0].id]
|
||||
);
|
||||
return done(null, emailUser.rows[0]);
|
||||
}
|
||||
@@ -48,16 +60,17 @@ if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
|
||||
`INSERT INTO users (email, first_name, last_name, oauth_provider, oauth_id)
|
||||
VALUES ($1, $2, $3, $4, $5) RETURNING *`,
|
||||
[
|
||||
profile.emails[0].value,
|
||||
profile.name.givenName,
|
||||
profile.name.familyName,
|
||||
'google',
|
||||
profile.id
|
||||
userInfo.email,
|
||||
userInfo.given_name || userInfo.name?.split(' ')[0] || 'User',
|
||||
userInfo.family_name || userInfo.name?.split(' ')[1] || '',
|
||||
'authentik',
|
||||
userInfo.sub
|
||||
]
|
||||
);
|
||||
|
||||
return done(null, newUser.rows[0]);
|
||||
} catch (error) {
|
||||
console.error('Authentik OAuth error:', error);
|
||||
return done(error, null);
|
||||
}
|
||||
}));
|
||||
@@ -185,18 +198,27 @@ router.post('/login', validateRequest(loginSchema), async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
// @route GET /api/auth/google
|
||||
// @desc Start Google OAuth2 flow
|
||||
// @route GET /api/auth/authentik
|
||||
// @desc Start Authentik OAuth2 flow
|
||||
// @access Public
|
||||
router.get('/google', passport.authenticate('google', {
|
||||
scope: ['profile', 'email']
|
||||
}));
|
||||
router.get('/authentik', (req, res, next) => {
|
||||
if (!process.env.AUTHENTIK_CLIENT_ID) {
|
||||
return res.status(503).json({
|
||||
success: false,
|
||||
message: 'Authentik OAuth not configured'
|
||||
});
|
||||
}
|
||||
|
||||
passport.authenticate('authentik', {
|
||||
scope: 'openid profile email'
|
||||
})(req, res, next);
|
||||
});
|
||||
|
||||
// @route GET /api/auth/google/callback
|
||||
// @desc Google OAuth2 callback
|
||||
// @route GET /api/auth/authentik/callback
|
||||
// @desc Authentik OAuth2 callback
|
||||
// @access Public
|
||||
router.get('/google/callback',
|
||||
passport.authenticate('google', { session: false }),
|
||||
router.get('/authentik/callback',
|
||||
passport.authenticate('authentik', { session: false }),
|
||||
(req, res) => {
|
||||
const token = generateToken(req.user.id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user