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.7 KiB
159 lines
5.7 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.end();
|
|
|
|
// 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.end();
|
|
return res.status(404).json({ error: "User not found" });
|
|
}
|
|
|
|
client.end();
|
|
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" });
|
|
}
|
|
}
|