leaderboard and ranked systems
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
const passport = require('passport');
|
||||
const { Strategy: GoogleStrategy } = require('passport-google-oauth20');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const db = require('../db');
|
||||
|
||||
async function generateUniqueUsername(base) {
|
||||
const candidate = base.toLowerCase();
|
||||
const taken = await db.user.findFirst({ where: { username: candidate } });
|
||||
if (!taken) return candidate;
|
||||
let attempts = 0;
|
||||
while (attempts < 20) {
|
||||
const suffix = String(Math.floor(1000 + Math.random() * 9000));
|
||||
const username = `${candidate}${suffix}`;
|
||||
const collision = await db.user.findFirst({ where: { username } });
|
||||
if (!collision) return username;
|
||||
attempts++;
|
||||
}
|
||||
return `${candidate}${Date.now()}`;
|
||||
}
|
||||
|
||||
passport.use(
|
||||
new GoogleStrategy(
|
||||
{
|
||||
clientID: process.env.GOOGLE_CLIENT_ID,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
callbackURL: process.env.GOOGLE_CALLBACK_URL,
|
||||
},
|
||||
async (_accessToken, _refreshToken, profile, done) => {
|
||||
try {
|
||||
const email = profile.emails?.[0]?.value ?? '';
|
||||
let user = await db.user.findUnique({ where: { googleId: profile.id } });
|
||||
|
||||
if (!user) {
|
||||
const username = await generateUniqueUsername(email.split('@')[0]);
|
||||
user = await db.user.create({
|
||||
data: {
|
||||
googleId: profile.id,
|
||||
email,
|
||||
displayName: profile.displayName,
|
||||
avatarUrl: profile.photos?.[0]?.value ?? null,
|
||||
username,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
user = await db.user.update({
|
||||
where: { googleId: profile.id },
|
||||
data: {
|
||||
email,
|
||||
displayName: profile.displayName,
|
||||
avatarUrl: profile.photos?.[0]?.value ?? null,
|
||||
},
|
||||
});
|
||||
if (!user.username) {
|
||||
const username = await generateUniqueUsername((user.email ?? '').split('@')[0]);
|
||||
user = await db.user.update({ where: { id: user.id }, data: { username } });
|
||||
}
|
||||
}
|
||||
|
||||
const token = jwt.sign(
|
||||
{
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
name: user.displayName,
|
||||
picture: user.avatarUrl,
|
||||
},
|
||||
process.env.JWT_SECRET,
|
||||
{ algorithm: 'HS256', expiresIn: '7d' }
|
||||
);
|
||||
|
||||
done(null, { token });
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
module.exports = passport;
|
||||
Reference in New Issue
Block a user