From faf349e0db2cb602a254f77f87fde7fbff4a993e Mon Sep 17 00:00:00 2001 From: Ruben Talstra Date: Wed, 12 Feb 2025 19:22:37 +0100 Subject: [PATCH] fix: Cosmos DB: `E11000` duplicate key error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- api/models/schema/userSchema.js | 32 +++++++------------------------- api/strategies/socialLogin.js | 7 +++++++ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/api/models/schema/userSchema.js b/api/models/schema/userSchema.js index ec4a1ef865..d2b30e1c37 100644 --- a/api/models/schema/userSchema.js +++ b/api/models/schema/userSchema.js @@ -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; diff --git a/api/strategies/socialLogin.js b/api/strategies/socialLogin.js index 4b900371d1..3602a5438a 100644 --- a/api/strategies/socialLogin.js +++ b/api/strategies/socialLogin.js @@ -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);