strapi-plugin-firebase-authentication 1.1.7 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{App-C49N6om4.mjs → App-C0XJYDQh.mjs} +34 -98
- package/dist/_chunks/{App-CtjmoTFU.js → App-COMAshYj.js} +34 -98
- package/dist/_chunks/{api-DrAXGM3H.mjs → api-CM79I13t.mjs} +1 -1
- package/dist/_chunks/{api-Bw_7tM52.js → api-DzbiYzK4.js} +1 -1
- package/dist/_chunks/{index-FAW4iPgh.mjs → index-4s0RQKAx.mjs} +2 -2
- package/dist/_chunks/{index-C9AUBuP7.mjs → index-B8sQntQh.mjs} +1 -1
- package/dist/_chunks/{index-yE1zATuU.js → index-DHMYqfl3.js} +2 -2
- package/dist/_chunks/{index-BkQ4pF_p.js → index-DyXjIUy8.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/forms/index.d.ts +2 -4
- package/dist/server/index.js +110 -52
- package/dist/server/index.mjs +110 -52
- package/dist/server/src/controllers/firebaseController.d.ts +0 -1
- package/dist/server/src/controllers/index.d.ts +0 -1
- package/dist/server/src/index.d.ts +4 -5
- package/dist/server/src/services/firebaseService.d.ts +3 -3
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/settingsService.d.ts +1 -2
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -199,8 +199,8 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
199
199
|
}
|
|
200
200
|
} catch (error2) {
|
|
201
201
|
strapi2.log.error("Firebase initialization failed during bootstrap:");
|
|
202
|
-
strapi2.log.error(
|
|
203
|
-
strapi2.log.error(
|
|
202
|
+
strapi2.log.error(` Error: ${error2.message}`);
|
|
203
|
+
strapi2.log.error(` Stack: ${error2.stack}`);
|
|
204
204
|
}
|
|
205
205
|
await strapi2.admin.services.permission.actionProvider.registerMany(actions);
|
|
206
206
|
if (strapi2.plugin("users-permissions")) {
|
|
@@ -210,14 +210,14 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
210
210
|
if (process.env.RUN_FIREBASE_MIGRATION === "true") {
|
|
211
211
|
const dryRun = process.env.DRY_RUN === "true";
|
|
212
212
|
strapi2.log.info("");
|
|
213
|
-
strapi2.log.info("
|
|
213
|
+
strapi2.log.info("Firebase migration triggered by RUN_FIREBASE_MIGRATION env variable");
|
|
214
214
|
await migrateFirebaseUserData(strapi2, dryRun);
|
|
215
215
|
}
|
|
216
216
|
setImmediate(async () => {
|
|
217
217
|
try {
|
|
218
218
|
await strapi2.plugin("firebase-authentication").service("autoLinkService").linkAllUsers(strapi2);
|
|
219
219
|
} catch (error2) {
|
|
220
|
-
strapi2.log.error(
|
|
220
|
+
strapi2.log.error(`Auto-linking failed: ${error2.message}`);
|
|
221
221
|
}
|
|
222
222
|
});
|
|
223
223
|
};
|
|
@@ -442,7 +442,7 @@ const firebaseController = {
|
|
|
442
442
|
const result = await strapi.plugin(pluginName).service("firebaseService").validateFirebaseToken(idToken, profileMetaData, populate2);
|
|
443
443
|
ctx.body = result;
|
|
444
444
|
} catch (error2) {
|
|
445
|
-
strapi.log.error(
|
|
445
|
+
strapi.log.error(`validateToken controller error: ${error2.message}`);
|
|
446
446
|
if (error2.name === "ValidationError") {
|
|
447
447
|
return ctx.badRequest(error2.message);
|
|
448
448
|
}
|
|
@@ -452,9 +452,6 @@ const firebaseController = {
|
|
|
452
452
|
throw error2;
|
|
453
453
|
}
|
|
454
454
|
},
|
|
455
|
-
async createAlias(ctx) {
|
|
456
|
-
ctx.body = await strapi.plugin(pluginName).service("firebaseService").createAlias(ctx);
|
|
457
|
-
},
|
|
458
455
|
async deleteByEmail(email2) {
|
|
459
456
|
const user = await strapi.firebase.auth().getUserByEmail(email2);
|
|
460
457
|
await strapi.plugin(pluginName).service("firebaseService").delete(user.toJSON().uid);
|
|
@@ -518,7 +515,8 @@ const firebaseController = {
|
|
|
518
515
|
async forgotPassword(ctx) {
|
|
519
516
|
strapi.log.debug("forgotPassword endpoint called");
|
|
520
517
|
try {
|
|
521
|
-
ctx.body
|
|
518
|
+
const { email: email2 } = ctx.request.body || {};
|
|
519
|
+
ctx.body = await strapi.plugin(pluginName).service("firebaseService").forgotPassword(email2);
|
|
522
520
|
} catch (error2) {
|
|
523
521
|
strapi.log.error("forgotPassword controller error:", error2);
|
|
524
522
|
if (error2.name === "ValidationError") {
|
|
@@ -541,7 +539,10 @@ const firebaseController = {
|
|
|
541
539
|
async resetPassword(ctx) {
|
|
542
540
|
strapi.log.debug("resetPassword endpoint called");
|
|
543
541
|
try {
|
|
544
|
-
ctx.body
|
|
542
|
+
const { password } = ctx.request.body || {};
|
|
543
|
+
const token = ctx.request.headers.authorization?.replace("Bearer ", "");
|
|
544
|
+
const populate2 = ctx.request.query.populate || [];
|
|
545
|
+
ctx.body = await strapi.plugin(pluginName).service("firebaseService").resetPassword(password, token, populate2);
|
|
545
546
|
} catch (error2) {
|
|
546
547
|
strapi.log.error("resetPassword controller error:", error2);
|
|
547
548
|
if (error2.name === "ValidationError" || error2.name === "UnauthorizedError") {
|
|
@@ -554,7 +555,8 @@ const firebaseController = {
|
|
|
554
555
|
},
|
|
555
556
|
async requestMagicLink(ctx) {
|
|
556
557
|
try {
|
|
557
|
-
const
|
|
558
|
+
const { email: email2 } = ctx.request.body || {};
|
|
559
|
+
const result = await strapi.plugin("firebase-authentication").service("firebaseService").requestMagicLink(email2);
|
|
558
560
|
ctx.body = result;
|
|
559
561
|
} catch (error2) {
|
|
560
562
|
if (error2.name === "ValidationError" || error2.name === "ApplicationError") {
|
|
@@ -28937,11 +28939,12 @@ const userController = {
|
|
|
28937
28939
|
};
|
|
28938
28940
|
const settingsController = {
|
|
28939
28941
|
setFirebaseConfigJson: async (ctx) => {
|
|
28940
|
-
|
|
28942
|
+
const requestBody = ctx.request.body;
|
|
28943
|
+
ctx.body = await strapi.plugin("firebase-authentication").service("settingsService").setFirebaseConfigJson(requestBody);
|
|
28941
28944
|
},
|
|
28942
28945
|
getFirebaseConfigJson: async (ctx) => {
|
|
28943
28946
|
try {
|
|
28944
|
-
const config2 = await strapi.plugin("firebase-authentication").service("settingsService").getFirebaseConfigJson(
|
|
28947
|
+
const config2 = await strapi.plugin("firebase-authentication").service("settingsService").getFirebaseConfigJson();
|
|
28945
28948
|
if (!config2) {
|
|
28946
28949
|
return ctx.send(null);
|
|
28947
28950
|
}
|
|
@@ -28954,7 +28957,7 @@ const settingsController = {
|
|
|
28954
28957
|
},
|
|
28955
28958
|
async delFirebaseConfigJson(ctx) {
|
|
28956
28959
|
try {
|
|
28957
|
-
const isExist = await strapi.plugin("firebase-authentication").service("settingsService").delFirebaseConfigJson(
|
|
28960
|
+
const isExist = await strapi.plugin("firebase-authentication").service("settingsService").delFirebaseConfigJson();
|
|
28958
28961
|
if (!isExist) {
|
|
28959
28962
|
throw new NotFoundError("No Firebase configs exists for deletion");
|
|
28960
28963
|
}
|
|
@@ -29281,7 +29284,7 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29281
29284
|
try {
|
|
29282
29285
|
strapi2.log.info("Starting Firebase initialization...");
|
|
29283
29286
|
const res = await strapi2.db.query(CONFIG_CONTENT_TYPE).findOne({ where: {} });
|
|
29284
|
-
strapi2.log.debug(
|
|
29287
|
+
strapi2.log.debug(`Found config: ${!!res}`);
|
|
29285
29288
|
if (!res) {
|
|
29286
29289
|
strapi2.log.debug("No config found, checking for existing Firebase app...");
|
|
29287
29290
|
if (strapi2.firebase) {
|
|
@@ -29291,7 +29294,7 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29291
29294
|
return;
|
|
29292
29295
|
}
|
|
29293
29296
|
const jsonObject = res["firebase_config_json"];
|
|
29294
|
-
strapi2.log.debug(
|
|
29297
|
+
strapi2.log.debug(`Config JSON present: ${!!jsonObject?.firebaseConfigJson}`);
|
|
29295
29298
|
if (!jsonObject || !jsonObject.firebaseConfigJson) {
|
|
29296
29299
|
strapi2.log.debug("No valid JSON config, checking for existing Firebase app...");
|
|
29297
29300
|
if (strapi2.firebase) {
|
|
@@ -29326,11 +29329,11 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29326
29329
|
strapi2.firebase = admin__default.default;
|
|
29327
29330
|
strapi2.log.info("Firebase initialization complete - admin instance attached to strapi.firebase");
|
|
29328
29331
|
} catch (initError) {
|
|
29329
|
-
strapi2.log.error(
|
|
29332
|
+
strapi2.log.error(`Failed to initialize Firebase: ${initError.message}`);
|
|
29330
29333
|
throw initError;
|
|
29331
29334
|
}
|
|
29332
29335
|
} catch (error2) {
|
|
29333
|
-
strapi2.log.error(
|
|
29336
|
+
strapi2.log.error(`Firebase bootstrap error: ${error2.message}`);
|
|
29334
29337
|
}
|
|
29335
29338
|
},
|
|
29336
29339
|
/**
|
|
@@ -29378,7 +29381,7 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29378
29381
|
magicLinkExpiryHours: configObject.magicLinkExpiryHours || 1
|
|
29379
29382
|
};
|
|
29380
29383
|
} catch (error2) {
|
|
29381
|
-
strapi2.log.error(
|
|
29384
|
+
strapi2.log.error(`Firebase config error: ${error2.message}`);
|
|
29382
29385
|
throw new ApplicationError$1("Error retrieving Firebase config", {
|
|
29383
29386
|
error: error2.message
|
|
29384
29387
|
});
|
|
@@ -29405,10 +29408,9 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29405
29408
|
* The service account JSON is encrypted using AES before storage,
|
|
29406
29409
|
* while the Web API key and password settings are stored in plain text.
|
|
29407
29410
|
*/
|
|
29408
|
-
async setFirebaseConfigJson(
|
|
29411
|
+
async setFirebaseConfigJson(requestBody) {
|
|
29409
29412
|
try {
|
|
29410
|
-
strapi2.log.debug("setFirebaseConfigJson"
|
|
29411
|
-
const { body: requestBody } = ctx.request;
|
|
29413
|
+
strapi2.log.debug("setFirebaseConfigJson called");
|
|
29412
29414
|
const firebaseConfigJsonString = requestBody.firebaseConfigJson;
|
|
29413
29415
|
const firebaseWebApiKey = requestBody.firebaseWebApiKey || null;
|
|
29414
29416
|
const {
|
|
@@ -29479,12 +29481,12 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29479
29481
|
const configData = res.firebaseConfigJson || res.firebase_config_json;
|
|
29480
29482
|
if (!configData) {
|
|
29481
29483
|
strapi2.log.error("Firebase config data missing from database response");
|
|
29482
|
-
strapi2.log.error(
|
|
29484
|
+
strapi2.log.error(`Available keys in response: ${JSON.stringify(Object.keys(res))}`);
|
|
29483
29485
|
throw new ApplicationError2("Failed to retrieve Firebase configuration from database");
|
|
29484
29486
|
}
|
|
29485
29487
|
const firebaseConfigHash = configData.firebaseConfigJson;
|
|
29486
29488
|
if (!firebaseConfigHash) {
|
|
29487
|
-
strapi2.log.error(
|
|
29489
|
+
strapi2.log.error(`Firebase config hash missing from config data: ${JSON.stringify(configData)}`);
|
|
29488
29490
|
throw new ApplicationError2("Firebase configuration hash is missing");
|
|
29489
29491
|
}
|
|
29490
29492
|
const firebaseConfigJsonValue = await this.decryptJson(encryptionKey, firebaseConfigHash);
|
|
@@ -29503,13 +29505,12 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29503
29505
|
return res;
|
|
29504
29506
|
} catch (error2) {
|
|
29505
29507
|
strapi2.log.error("=== FIREBASE CONFIG SAVE ERROR ===");
|
|
29506
|
-
strapi2.log.error(
|
|
29507
|
-
strapi2.log.error(
|
|
29508
|
-
strapi2.log.error(
|
|
29508
|
+
strapi2.log.error(`Error name: ${error2.name}`);
|
|
29509
|
+
strapi2.log.error(`Error message: ${error2.message}`);
|
|
29510
|
+
strapi2.log.error(`Error stack: ${error2.stack}`);
|
|
29509
29511
|
try {
|
|
29510
|
-
|
|
29511
|
-
|
|
29512
|
-
strapi2.log.error("Request body keys:", Object.keys(body));
|
|
29512
|
+
if (requestBody) {
|
|
29513
|
+
strapi2.log.error(`Request body keys: ${JSON.stringify(Object.keys(requestBody))}`);
|
|
29513
29514
|
}
|
|
29514
29515
|
} catch (e) {
|
|
29515
29516
|
strapi2.log.error("Could not access request body");
|
|
@@ -29530,7 +29531,7 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29530
29531
|
try {
|
|
29531
29532
|
strapi2.log.debug("delFirebaseConfigJson called");
|
|
29532
29533
|
const isExist = await strapi2.db.query(CONFIG_CONTENT_TYPE).findOne({ where: {} });
|
|
29533
|
-
strapi2.log.debug(
|
|
29534
|
+
strapi2.log.debug(`Config exists: ${!!isExist}`);
|
|
29534
29535
|
if (!isExist) {
|
|
29535
29536
|
strapi2.log.info(ERROR_MESSAGES.DELETION_NO_CONFIG);
|
|
29536
29537
|
return null;
|
|
@@ -29538,12 +29539,12 @@ const settingsService = ({ strapi: strapi2 }) => {
|
|
|
29538
29539
|
const res = await strapi2.db.query(CONFIG_CONTENT_TYPE).delete({
|
|
29539
29540
|
where: { id: isExist.id }
|
|
29540
29541
|
});
|
|
29541
|
-
strapi2.log.debug(
|
|
29542
|
+
strapi2.log.debug(`Delete result: ${JSON.stringify(res)}`);
|
|
29542
29543
|
await strapi2.plugin("firebase-authentication").service("settingsService").init();
|
|
29543
29544
|
strapi2.log.info(SUCCESS_MESSAGES.FIREBASE_CONFIG_DELETED);
|
|
29544
29545
|
return res;
|
|
29545
29546
|
} catch (error2) {
|
|
29546
|
-
strapi2.log.error(
|
|
29547
|
+
strapi2.log.error(`delFirebaseConfigJson error: ${error2.message}`);
|
|
29547
29548
|
throw new ApplicationError2(ERROR_MESSAGES.SOMETHING_WENT_WRONG, {
|
|
29548
29549
|
error: error2
|
|
29549
29550
|
});
|
|
@@ -30466,8 +30467,8 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30466
30467
|
* Forgot password flow - sends reset email
|
|
30467
30468
|
* Public endpoint that sends a Firebase-hosted password reset email using Firebase's secure hosted UI
|
|
30468
30469
|
*/
|
|
30469
|
-
forgotPassword: async (
|
|
30470
|
-
|
|
30470
|
+
forgotPassword: async (email2) => {
|
|
30471
|
+
strapi2.log.info(`[forgotPassword] Starting password reset for email: ${email2}`);
|
|
30471
30472
|
if (!email2) {
|
|
30472
30473
|
throw new ValidationError$1("Email is required");
|
|
30473
30474
|
}
|
|
@@ -30508,8 +30509,16 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30508
30509
|
});
|
|
30509
30510
|
}
|
|
30510
30511
|
if (!strapiUser) {
|
|
30512
|
+
strapi2.log.warn(`⚠️ [forgotPassword] User not found for email: ${email2}`);
|
|
30511
30513
|
return { message: "If an account with that email exists, a password reset link has been sent." };
|
|
30512
30514
|
}
|
|
30515
|
+
strapi2.log.info(
|
|
30516
|
+
`✅ [forgotPassword] User found: ${JSON.stringify({
|
|
30517
|
+
documentId: strapiUser.documentId,
|
|
30518
|
+
email: strapiUser.email,
|
|
30519
|
+
firebaseUID: firebaseUser?.uid || "not in Firebase"
|
|
30520
|
+
})}`
|
|
30521
|
+
);
|
|
30513
30522
|
const actionCodeSettings = {
|
|
30514
30523
|
url: resetUrl,
|
|
30515
30524
|
// Continue URL after reset completes on Firebase's page
|
|
@@ -30523,6 +30532,7 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30523
30532
|
});
|
|
30524
30533
|
let resetLink;
|
|
30525
30534
|
try {
|
|
30535
|
+
strapi2.log.info(`[forgotPassword] Generating Firebase password reset link for: ${strapiUser.email}`);
|
|
30526
30536
|
resetLink = await Promise.race([
|
|
30527
30537
|
strapi2.firebase.auth().generatePasswordResetLink(strapiUser.email, actionCodeSettings),
|
|
30528
30538
|
timeoutPromise
|
|
@@ -30534,12 +30544,22 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30534
30544
|
strapi2.log.error(`❌ Failed to generate password reset link for ${strapiUser.email}:`, error2);
|
|
30535
30545
|
throw error2;
|
|
30536
30546
|
}
|
|
30547
|
+
strapi2.log.info(`[forgotPassword] Attempting to send password reset email to: ${strapiUser.email}`);
|
|
30537
30548
|
await strapi2.plugin("firebase-authentication").service("emailService").sendPasswordResetEmail(strapiUser, resetLink);
|
|
30549
|
+
strapi2.log.info(`✅ [forgotPassword] Password reset email sent successfully to: ${strapiUser.email}`);
|
|
30538
30550
|
return {
|
|
30539
30551
|
message: "If an account with that email exists, a password reset link has been sent."
|
|
30540
30552
|
};
|
|
30541
30553
|
} catch (error2) {
|
|
30542
|
-
strapi2.log.error(
|
|
30554
|
+
strapi2.log.error(
|
|
30555
|
+
`❌ [forgotPassword] ERROR: ${JSON.stringify({
|
|
30556
|
+
email: email2,
|
|
30557
|
+
message: error2.message,
|
|
30558
|
+
code: error2.code,
|
|
30559
|
+
name: error2.name,
|
|
30560
|
+
stack: error2.stack
|
|
30561
|
+
})}`
|
|
30562
|
+
);
|
|
30543
30563
|
return {
|
|
30544
30564
|
message: "If an account with that email exists, a password reset link has been sent."
|
|
30545
30565
|
};
|
|
@@ -30559,13 +30579,10 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30559
30579
|
*
|
|
30560
30580
|
* NOT used for forgot password email flow - that now uses Firebase's hosted UI
|
|
30561
30581
|
*/
|
|
30562
|
-
resetPassword: async (
|
|
30563
|
-
const { password } = ctx.request.body;
|
|
30564
|
-
const populate2 = ctx.request.query.populate || [];
|
|
30582
|
+
resetPassword: async (password, token, populate2) => {
|
|
30565
30583
|
if (!password) {
|
|
30566
30584
|
throw new ValidationError$1("Password is required");
|
|
30567
30585
|
}
|
|
30568
|
-
const token = ctx.request.header.authorization?.replace("Bearer ", "");
|
|
30569
30586
|
if (!token) {
|
|
30570
30587
|
throw new UnauthorizedError("Authorization token is required");
|
|
30571
30588
|
}
|
|
@@ -30621,8 +30638,7 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30621
30638
|
* Generates a sign-in link using Firebase Admin SDK
|
|
30622
30639
|
* Note: Verification requires client-side completion
|
|
30623
30640
|
*/
|
|
30624
|
-
async requestMagicLink(
|
|
30625
|
-
const { email: email2 } = ctx.request.body;
|
|
30641
|
+
async requestMagicLink(email2) {
|
|
30626
30642
|
if (!email2 || typeof email2 !== "string") {
|
|
30627
30643
|
throw new ValidationError$1("Valid email is required");
|
|
30628
30644
|
}
|
|
@@ -30652,7 +30668,7 @@ const firebaseService = ({ strapi: strapi2 }) => ({
|
|
|
30652
30668
|
};
|
|
30653
30669
|
const magicLink = await strapi2.firebase.auth().generateSignInWithEmailLink(email2, actionCodeSettings);
|
|
30654
30670
|
if (process.env.NODE_ENV !== "production") {
|
|
30655
|
-
strapi2.log.info("
|
|
30671
|
+
strapi2.log.info("Magic Link Generation Request:");
|
|
30656
30672
|
strapi2.log.info(` Email: ${email2}`);
|
|
30657
30673
|
strapi2.log.info(` Verification URL: ${magicLinkUrl}`);
|
|
30658
30674
|
strapi2.log.info(` Expires: ${config2.magicLinkExpiryHours || 1} hour(s)`);
|
|
@@ -31258,7 +31274,7 @@ class EmailService {
|
|
|
31258
31274
|
const template = await templateService2.getTemplate("magicLink");
|
|
31259
31275
|
const compiledSubject = _$1.template(template.subject)(completeVariables);
|
|
31260
31276
|
strapi.log.info("\n" + "=".repeat(80));
|
|
31261
|
-
strapi.log.info("
|
|
31277
|
+
strapi.log.info("MAGIC LINK EMAIL (Development Mode)");
|
|
31262
31278
|
strapi.log.info("=".repeat(80));
|
|
31263
31279
|
strapi.log.info(`To: ${email2}`);
|
|
31264
31280
|
strapi.log.info(`Subject: ${compiledSubject}`);
|
|
@@ -31373,7 +31389,7 @@ const autoLinkService = {
|
|
|
31373
31389
|
errors: 0
|
|
31374
31390
|
};
|
|
31375
31391
|
try {
|
|
31376
|
-
strapi2.log.info("
|
|
31392
|
+
strapi2.log.info("Auto-linking Strapi users with Firebase users...");
|
|
31377
31393
|
if (!strapi2.firebase) {
|
|
31378
31394
|
strapi2.log.warn("Firebase not initialized - skipping auto-linking");
|
|
31379
31395
|
return result;
|
|
@@ -31412,6 +31428,7 @@ const autoLinkService = {
|
|
|
31412
31428
|
}
|
|
31413
31429
|
}
|
|
31414
31430
|
for (const strapiUser of strapiUsers) {
|
|
31431
|
+
let firebaseUser = null;
|
|
31415
31432
|
try {
|
|
31416
31433
|
const existing = await strapi2.db.query("plugin::firebase-authentication.firebase-user-data").findOne({
|
|
31417
31434
|
select: ["id"],
|
|
@@ -31421,7 +31438,7 @@ const autoLinkService = {
|
|
|
31421
31438
|
result.skipped++;
|
|
31422
31439
|
continue;
|
|
31423
31440
|
}
|
|
31424
|
-
|
|
31441
|
+
firebaseUser = null;
|
|
31425
31442
|
if (strapiUser.email) {
|
|
31426
31443
|
firebaseUser = firebaseByEmail.get(strapiUser.email.toLowerCase());
|
|
31427
31444
|
}
|
|
@@ -31432,6 +31449,23 @@ const autoLinkService = {
|
|
|
31432
31449
|
result.skipped++;
|
|
31433
31450
|
continue;
|
|
31434
31451
|
}
|
|
31452
|
+
const existingUIDLink = await strapi2.db.query("plugin::firebase-authentication.firebase-user-data").findOne({
|
|
31453
|
+
where: { firebaseUserID: firebaseUser.uid },
|
|
31454
|
+
populate: ["user"]
|
|
31455
|
+
});
|
|
31456
|
+
if (existingUIDLink && existingUIDLink.user?.documentId !== strapiUser.documentId) {
|
|
31457
|
+
strapi2.log.warn(
|
|
31458
|
+
`⚠️ [Auto-Link] Skipping '${strapiUser.username || strapiUser.email}' - Firebase UID already linked`
|
|
31459
|
+
);
|
|
31460
|
+
strapi2.log.warn(` Strapi User: ${strapiUser.email} (documentId: ${strapiUser.documentId})`);
|
|
31461
|
+
strapi2.log.warn(` Firebase UID: ${firebaseUser.uid}`);
|
|
31462
|
+
strapi2.log.warn(
|
|
31463
|
+
` Already linked to: ${existingUIDLink.user?.email} (documentId: ${existingUIDLink.user?.documentId})`
|
|
31464
|
+
);
|
|
31465
|
+
strapi2.log.warn(` Action: Resolve duplicate users or manually unlink conflicting record`);
|
|
31466
|
+
result.skipped++;
|
|
31467
|
+
continue;
|
|
31468
|
+
}
|
|
31435
31469
|
try {
|
|
31436
31470
|
const firebaseData = {
|
|
31437
31471
|
firebaseUserID: firebaseUser.uid
|
|
@@ -31450,18 +31484,42 @@ const autoLinkService = {
|
|
|
31450
31484
|
throw createError;
|
|
31451
31485
|
}
|
|
31452
31486
|
} catch (error2) {
|
|
31453
|
-
|
|
31454
|
-
|
|
31487
|
+
if (error2.message?.includes("This attribute must be unique")) {
|
|
31488
|
+
strapi2.log.warn(
|
|
31489
|
+
`⚠️ [Auto-Link] Unique constraint conflict for '${strapiUser.username || strapiUser.email}'`
|
|
31490
|
+
);
|
|
31491
|
+
strapi2.log.warn(` Strapi User: ${strapiUser.email} (documentId: ${strapiUser.documentId})`);
|
|
31492
|
+
if (firebaseUser) {
|
|
31493
|
+
strapi2.log.warn(` Firebase UID: ${firebaseUser.uid}`);
|
|
31494
|
+
strapi2.log.warn(` Cause: This Firebase UID is already linked to another Strapi user`);
|
|
31495
|
+
strapi2.log.warn(
|
|
31496
|
+
` Action: Query firebase_user_data table to find conflict - WHERE firebase_user_id = '${firebaseUser.uid}'`
|
|
31497
|
+
);
|
|
31498
|
+
}
|
|
31499
|
+
result.skipped++;
|
|
31500
|
+
} else {
|
|
31501
|
+
result.errors++;
|
|
31502
|
+
strapi2.log.error(
|
|
31503
|
+
`❌ [Auto-Link] Unexpected error linking user '${strapiUser.username || strapiUser.email}': ${error2.message}`
|
|
31504
|
+
);
|
|
31505
|
+
}
|
|
31455
31506
|
}
|
|
31456
31507
|
}
|
|
31457
|
-
|
|
31458
|
-
|
|
31459
|
-
|
|
31508
|
+
if (result.errors > 0) {
|
|
31509
|
+
strapi2.log.error(
|
|
31510
|
+
`❌ Auto-linking completed with unexpected errors: ${result.linked} linked, ${result.skipped} skipped, ${result.errors} errors`
|
|
31511
|
+
);
|
|
31512
|
+
strapi2.log.error(` Review error logs above for resolution steps`);
|
|
31513
|
+
} else {
|
|
31514
|
+
strapi2.log.info(
|
|
31515
|
+
`✅ Auto-linking complete: ${result.linked} linked, ${result.skipped} skipped, ${result.errors} errors`
|
|
31516
|
+
);
|
|
31517
|
+
}
|
|
31460
31518
|
strapi2.log.info(
|
|
31461
31519
|
` Total: ${result.totalStrapiUsers} Strapi users, ${result.totalFirebaseUsers} Firebase users`
|
|
31462
31520
|
);
|
|
31463
31521
|
} catch (error2) {
|
|
31464
|
-
strapi2.log.error(
|
|
31522
|
+
strapi2.log.error(`❌ Fatal error during auto-linking: ${error2.message}`);
|
|
31465
31523
|
}
|
|
31466
31524
|
return result;
|
|
31467
31525
|
}
|