You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

159 lines
5.8 KiB

import passport from "passport";
import { Strategy as GitHubStrategy } from "passport-github2";
import { getClient } from "../utils/database.js";
import jwt from "jsonwebtoken";
export async function login(req, res) {
passport.authenticate("github", { scope: ["user:email"] })(req, res);
}
export async function callback(req, res, next) {
passport.authenticate("github", { failureRedirect: "https://localhost/login?error=oauth_failed" }, async (err, user) => {
if (err) {
console.error("OAuth error:", err);
return res.redirect("https://localhost/login?error=oauth_error");
}
if (!user) {
return res.redirect("https://localhost/login?error=oauth_cancelled");
}
try {
// Extract user information from GitHub profile
const githubId = user.id;
const username = user.username || user.login;
const email = user.emails[0].value || null;
const avatarUrl = user.photos && user.photos[0] ? user.photos[0].value : null;
const displayName = user.displayName || username;
console.log(user);
console.log("GitHub user info:", {
githubId,
username,
email,
displayName,
avatarUrl
});
const client = await getClient();
// Check if user already exists by GitHub ID
let existingUserQuery = `SELECT * FROM users WHERE github_id = $1`;
let existingUserResult = await client.query(existingUserQuery, [githubId]);
let dbUser;
if (existingUserResult.rows.length > 0) {
// User exists, update their information
dbUser = existingUserResult.rows[0];
const updateQuery = `UPDATE users SET
username = $1,
email = $2,
picture = $3,
is_verified = true,
updated_at = NOW()
WHERE github_id = $4
RETURNING id, username, email, picture`;
const updateResult = await client.query(updateQuery, [
username,
email,
avatarUrl || "/api/media/profile/default.png",
githubId
]);
dbUser = updateResult.rows[0];
} else {
// Check if username already exists
const usernameCheck = await client.query(`SELECT id FROM users WHERE username = $1`, [username]);
let finalUsername = username;
if (usernameCheck.rows.length > 0) {
// Username exists, append GitHub ID to make it unique
finalUsername = `${username}_gh${githubId}`;
}
// Create new user
const insertQuery = `INSERT INTO users (
username,
email,
picture,
github_id,
password,
is_verified
) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, username, email, picture`;
const insertResult = await client.query(insertQuery, [
finalUsername,
email,
avatarUrl || "/api/media/profile/default.png",
githubId,
null, // No password for OAuth users
true // OAuth users are automatically verified
]);
dbUser = insertResult.rows[0];
// Create default playlist for new user
const playlistQuery = `INSERT INTO playlists (name, owner) VALUES ('A regarder plus tard', $1)`;
await client.query(playlistQuery, [dbUser.id]);
}
client.release();
// Generate JWT token
const payload = {
id: dbUser.id,
username: dbUser.username,
};
const token = jwt.sign(payload, process.env.JWT_SECRET);
// Redirect to frontend with token and user info
const userData = encodeURIComponent(JSON.stringify({
id: dbUser.id,
username: dbUser.username,
email: dbUser.email,
picture: dbUser.picture
}));
res.redirect(`https://localhost/login/success?token=${token}&user=${userData}`);
} catch (error) {
console.error("Error processing GitHub OAuth callback:", error);
res.redirect("https://localhost/login?error=processing_error");
}
})(req, res, next);
}
export async function getUserInfo(req, res) {
try {
// This endpoint can be used to get current user info from token
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
return res.status(401).json({ error: "No token provided" });
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const client = await getClient();
const query = `SELECT id, username, email, picture, github_id, is_verified FROM users WHERE id = $1`;
const result = await client.query(query, [decoded.id]);
if (!result.rows[0]) {
client.release();
return res.status(404).json({ error: "User not found" });
}
client.release();
res.status(200).json({ user: result.rows[0] });
} catch (error) {
console.error("Error getting user info:", error);
res.status(500).json({ error: "Internal server error" });
}
}