fix: Cosmos DB: E11000 duplicate key error

I’ve updated this PR to remove unique: true and sparse: true from the optional social login fields (googleId, facebookId, etc.) and switch them to simple indexes (index: true). This resolves the Cosmos DB “duplicate key” errors caused by multiple null values and ensures compatibility with both Cosmos DB and MongoDB. The email field remains required and unique, preserving overall identity uniqueness.
This commit is contained in:
Ruben Talstra 2025-02-12 19:22:37 +01:00
parent 915022bc08
commit faf349e0db
Failed to extract signature
2 changed files with 14 additions and 25 deletions

View file

@ -84,28 +84,31 @@ const userSchema = mongoose.Schema(
},
googleId: {
type: String,
index: true,
},
facebookId: {
type: String,
index: true,
},
openidId: {
type: String,
index: true,
},
ldapId: {
type: String,
unique: true,
sparse: true,
index: true,
},
githubId: {
type: String,
index: true,
},
discordId: {
type: String,
index: true,
},
appleId: {
type: String,
unique: true,
sparse: true,
index: true,
},
plugins: {
type: Array,
@ -127,25 +130,4 @@ const userSchema = mongoose.Schema(
{ timestamps: true },
);
userSchema.index(
{ googleId: 1 },
{ unique: true, partialFilterExpression: { googleId: { $type: 'string' } } },
);
userSchema.index(
{ facebookId: 1 },
{ unique: true, partialFilterExpression: { facebookId: { $type: 'string' } } },
);
userSchema.index(
{ openidId: 1 },
{ unique: true, partialFilterExpression: { openidId: { $type: 'string' } } },
);
userSchema.index(
{ githubId: 1 },
{ unique: true, partialFilterExpression: { githubId: { $type: 'string' } } },
);
userSchema.index(
{ discordId: 1 },
{ unique: true, partialFilterExpression: { discordId: { $type: 'string' } } },
);
module.exports = userSchema;

View file

@ -3,6 +3,11 @@ const { isEnabled } = require('~/server/utils');
const { findUser } = require('~/models');
const { logger } = require('~/config');
/**
* Returns a function that handles the social login flow for a given provider.
* @param {string} provider - The provider name (e.g. 'google', 'facebook').
* @param {Function} getProfileDetails - A function to extract user details from the provider profile.
*/
const socialLogin =
(provider, getProfileDetails) => async (accessToken, refreshToken, idToken, profile, cb) => {
try {
@ -31,6 +36,8 @@ const socialLogin =
});
return cb(null, newUser);
}
return cb(null, null);
} catch (err) {
logger.error(`[${provider}Login]`, err);
return cb(err);