@blackcode_sa/metaestetics-api 1.14.0 → 1.14.1
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/index.js +122 -8
- package/dist/index.mjs +122 -8
- package/package.json +1 -1
- package/src/services/auth/auth.service.ts +125 -8
- package/src/services/practitioner/practitioner.service.ts +25 -0
package/dist/index.js
CHANGED
|
@@ -11308,6 +11308,9 @@ var PractitionerService = class extends BaseService {
|
|
|
11308
11308
|
*/
|
|
11309
11309
|
async processBasicInfo(basicInfo, practitionerId) {
|
|
11310
11310
|
const processedBasicInfo = { ...basicInfo };
|
|
11311
|
+
if (processedBasicInfo.email) {
|
|
11312
|
+
processedBasicInfo.email = processedBasicInfo.email.toLowerCase().trim();
|
|
11313
|
+
}
|
|
11311
11314
|
if (basicInfo.profileImageUrl) {
|
|
11312
11315
|
const uploadedUrl = await this.handleProfilePhotoUpload(
|
|
11313
11316
|
basicInfo.profileImageUrl,
|
|
@@ -11731,7 +11734,8 @@ var PractitionerService = class extends BaseService {
|
|
|
11731
11734
|
try {
|
|
11732
11735
|
const normalizedEmail = email.toLowerCase().trim();
|
|
11733
11736
|
console.log("[PRACTITIONER] Searching for all draft practitioners by email", {
|
|
11734
|
-
email: normalizedEmail
|
|
11737
|
+
email: normalizedEmail,
|
|
11738
|
+
originalEmail: email
|
|
11735
11739
|
});
|
|
11736
11740
|
const q = (0, import_firestore32.query)(
|
|
11737
11741
|
(0, import_firestore32.collection)(this.db, PRACTITIONERS_COLLECTION),
|
|
@@ -11742,7 +11746,26 @@ var PractitionerService = class extends BaseService {
|
|
|
11742
11746
|
const querySnapshot = await (0, import_firestore32.getDocs)(q);
|
|
11743
11747
|
if (querySnapshot.empty) {
|
|
11744
11748
|
console.log("[PRACTITIONER] No draft practitioners found for email", {
|
|
11745
|
-
email: normalizedEmail
|
|
11749
|
+
email: normalizedEmail,
|
|
11750
|
+
originalEmail: email
|
|
11751
|
+
});
|
|
11752
|
+
const debugQ = (0, import_firestore32.query)(
|
|
11753
|
+
(0, import_firestore32.collection)(this.db, PRACTITIONERS_COLLECTION),
|
|
11754
|
+
(0, import_firestore32.where)("basicInfo.email", "==", normalizedEmail),
|
|
11755
|
+
(0, import_firestore32.limit)(5)
|
|
11756
|
+
);
|
|
11757
|
+
const debugSnapshot = await (0, import_firestore32.getDocs)(debugQ);
|
|
11758
|
+
console.log("[PRACTITIONER] Debug: Found practitioners with this email (any status):", {
|
|
11759
|
+
count: debugSnapshot.size,
|
|
11760
|
+
practitioners: debugSnapshot.docs.map((doc47) => {
|
|
11761
|
+
var _a;
|
|
11762
|
+
return {
|
|
11763
|
+
id: doc47.id,
|
|
11764
|
+
email: (_a = doc47.data().basicInfo) == null ? void 0 : _a.email,
|
|
11765
|
+
status: doc47.data().status,
|
|
11766
|
+
userRef: doc47.data().userRef
|
|
11767
|
+
};
|
|
11768
|
+
})
|
|
11746
11769
|
});
|
|
11747
11770
|
return [];
|
|
11748
11771
|
}
|
|
@@ -16029,6 +16052,7 @@ var AuthService = class extends BaseService {
|
|
|
16029
16052
|
* @returns Object containing user, practitioner (if exists), and draft profiles (if any)
|
|
16030
16053
|
*/
|
|
16031
16054
|
async signUpPractitionerWithGoogle(idToken) {
|
|
16055
|
+
var _a, _b;
|
|
16032
16056
|
try {
|
|
16033
16057
|
console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
|
|
16034
16058
|
let email;
|
|
@@ -16062,12 +16086,48 @@ var AuthService = class extends BaseService {
|
|
|
16062
16086
|
console.log("[AUTH] User exists with Google provider, signing in");
|
|
16063
16087
|
const credential2 = import_auth8.GoogleAuthProvider.credential(idToken);
|
|
16064
16088
|
const { user: firebaseUser2 } = await (0, import_auth8.signInWithCredential)(this.auth, credential2);
|
|
16065
|
-
|
|
16089
|
+
let existingUser2 = null;
|
|
16090
|
+
try {
|
|
16091
|
+
existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
|
|
16092
|
+
console.log("[AUTH] User document found:", existingUser2.uid);
|
|
16093
|
+
} catch (userError) {
|
|
16094
|
+
console.log("[AUTH] User document not found in Firestore, checking for draft profiles", {
|
|
16095
|
+
errorCode: userError == null ? void 0 : userError.code,
|
|
16096
|
+
errorMessage: userError == null ? void 0 : userError.message,
|
|
16097
|
+
errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
|
|
16098
|
+
isAuthError: userError instanceof AuthError
|
|
16099
|
+
});
|
|
16100
|
+
const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
|
|
16101
|
+
const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
|
|
16102
|
+
console.log("[AUTH] Draft profiles check result:", {
|
|
16103
|
+
email: normalizedEmail,
|
|
16104
|
+
draftProfilesCount: draftProfiles3.length,
|
|
16105
|
+
draftProfileIds: draftProfiles3.map((p) => p.id)
|
|
16106
|
+
});
|
|
16107
|
+
if (draftProfiles3.length === 0) {
|
|
16108
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16109
|
+
try {
|
|
16110
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16111
|
+
} catch (signOutError) {
|
|
16112
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16113
|
+
}
|
|
16114
|
+
throw new AuthError(
|
|
16115
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16116
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16117
|
+
404
|
|
16118
|
+
);
|
|
16119
|
+
}
|
|
16120
|
+
console.log("[AUTH] Draft profiles found, creating user document");
|
|
16121
|
+
existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
|
|
16122
|
+
skipProfileCreation: true
|
|
16123
|
+
});
|
|
16124
|
+
console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
|
|
16125
|
+
}
|
|
16066
16126
|
if (!existingUser2) {
|
|
16067
16127
|
await (0, import_auth8.signOut)(this.auth);
|
|
16068
16128
|
throw new AuthError(
|
|
16069
|
-
"No
|
|
16070
|
-
"AUTH/
|
|
16129
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16130
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16071
16131
|
404
|
|
16072
16132
|
);
|
|
16073
16133
|
}
|
|
@@ -16117,16 +16177,47 @@ var AuthService = class extends BaseService {
|
|
|
16117
16177
|
console.error("[AUTH] Error checking for existing user:", error);
|
|
16118
16178
|
}
|
|
16119
16179
|
console.log("[AUTH] Checking for draft profiles");
|
|
16120
|
-
|
|
16180
|
+
let draftProfiles = [];
|
|
16181
|
+
try {
|
|
16182
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
16183
|
+
console.log("[AUTH] Draft profiles check complete", { count: draftProfiles.length });
|
|
16184
|
+
} catch (draftCheckError) {
|
|
16185
|
+
console.error("[AUTH] Error checking draft profiles:", draftCheckError);
|
|
16186
|
+
try {
|
|
16187
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16188
|
+
} catch (signOutError) {
|
|
16189
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16190
|
+
}
|
|
16191
|
+
throw new AuthError(
|
|
16192
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16193
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16194
|
+
404
|
|
16195
|
+
);
|
|
16196
|
+
}
|
|
16121
16197
|
let user;
|
|
16122
16198
|
if (existingUser) {
|
|
16123
16199
|
user = existingUser;
|
|
16124
16200
|
console.log("[AUTH] Using existing user account");
|
|
16125
16201
|
} else {
|
|
16202
|
+
if (draftProfiles.length === 0) {
|
|
16203
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16204
|
+
try {
|
|
16205
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16206
|
+
} catch (signOutError) {
|
|
16207
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16208
|
+
}
|
|
16209
|
+
const noDraftError = new AuthError(
|
|
16210
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16211
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16212
|
+
404
|
|
16213
|
+
);
|
|
16214
|
+
console.log("[AUTH] Throwing NO_DRAFT_PROFILES error:", noDraftError.code);
|
|
16215
|
+
throw noDraftError;
|
|
16216
|
+
}
|
|
16126
16217
|
user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
|
|
16127
16218
|
skipProfileCreation: true
|
|
16128
16219
|
});
|
|
16129
|
-
console.log("[AUTH] Created new user account");
|
|
16220
|
+
console.log("[AUTH] Created new user account with draft profiles available");
|
|
16130
16221
|
}
|
|
16131
16222
|
let practitioner = null;
|
|
16132
16223
|
if (user.practitionerProfile) {
|
|
@@ -16144,10 +16235,33 @@ var AuthService = class extends BaseService {
|
|
|
16144
16235
|
};
|
|
16145
16236
|
} catch (error) {
|
|
16146
16237
|
console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
|
|
16238
|
+
console.error("[AUTH] Error type:", (_b = error == null ? void 0 : error.constructor) == null ? void 0 : _b.name);
|
|
16239
|
+
console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
|
|
16240
|
+
console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
|
|
16241
|
+
console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
|
|
16147
16242
|
if (error instanceof AuthError) {
|
|
16243
|
+
console.log("[AUTH] Preserving AuthError:", error.code);
|
|
16148
16244
|
throw error;
|
|
16149
16245
|
}
|
|
16150
|
-
|
|
16246
|
+
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "";
|
|
16247
|
+
if (errorMessage.includes("NO_DRAFT_PROFILES") || errorMessage.includes("clinic invitation")) {
|
|
16248
|
+
console.log("[AUTH] Detected clinic invitation error in message, converting to AuthError");
|
|
16249
|
+
throw new AuthError(
|
|
16250
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16251
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16252
|
+
404
|
|
16253
|
+
);
|
|
16254
|
+
}
|
|
16255
|
+
const wrappedError = handleFirebaseError(error);
|
|
16256
|
+
console.log("[AUTH] Wrapped error:", wrappedError.message);
|
|
16257
|
+
if (wrappedError.message.includes("permissions") || wrappedError.message.includes("Account creation failed")) {
|
|
16258
|
+
throw new AuthError(
|
|
16259
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16260
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16261
|
+
404
|
|
16262
|
+
);
|
|
16263
|
+
}
|
|
16264
|
+
throw wrappedError;
|
|
16151
16265
|
}
|
|
16152
16266
|
}
|
|
16153
16267
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -11331,6 +11331,9 @@ var PractitionerService = class extends BaseService {
|
|
|
11331
11331
|
*/
|
|
11332
11332
|
async processBasicInfo(basicInfo, practitionerId) {
|
|
11333
11333
|
const processedBasicInfo = { ...basicInfo };
|
|
11334
|
+
if (processedBasicInfo.email) {
|
|
11335
|
+
processedBasicInfo.email = processedBasicInfo.email.toLowerCase().trim();
|
|
11336
|
+
}
|
|
11334
11337
|
if (basicInfo.profileImageUrl) {
|
|
11335
11338
|
const uploadedUrl = await this.handleProfilePhotoUpload(
|
|
11336
11339
|
basicInfo.profileImageUrl,
|
|
@@ -11754,7 +11757,8 @@ var PractitionerService = class extends BaseService {
|
|
|
11754
11757
|
try {
|
|
11755
11758
|
const normalizedEmail = email.toLowerCase().trim();
|
|
11756
11759
|
console.log("[PRACTITIONER] Searching for all draft practitioners by email", {
|
|
11757
|
-
email: normalizedEmail
|
|
11760
|
+
email: normalizedEmail,
|
|
11761
|
+
originalEmail: email
|
|
11758
11762
|
});
|
|
11759
11763
|
const q = query13(
|
|
11760
11764
|
collection13(this.db, PRACTITIONERS_COLLECTION),
|
|
@@ -11765,7 +11769,26 @@ var PractitionerService = class extends BaseService {
|
|
|
11765
11769
|
const querySnapshot = await getDocs13(q);
|
|
11766
11770
|
if (querySnapshot.empty) {
|
|
11767
11771
|
console.log("[PRACTITIONER] No draft practitioners found for email", {
|
|
11768
|
-
email: normalizedEmail
|
|
11772
|
+
email: normalizedEmail,
|
|
11773
|
+
originalEmail: email
|
|
11774
|
+
});
|
|
11775
|
+
const debugQ = query13(
|
|
11776
|
+
collection13(this.db, PRACTITIONERS_COLLECTION),
|
|
11777
|
+
where13("basicInfo.email", "==", normalizedEmail),
|
|
11778
|
+
limit7(5)
|
|
11779
|
+
);
|
|
11780
|
+
const debugSnapshot = await getDocs13(debugQ);
|
|
11781
|
+
console.log("[PRACTITIONER] Debug: Found practitioners with this email (any status):", {
|
|
11782
|
+
count: debugSnapshot.size,
|
|
11783
|
+
practitioners: debugSnapshot.docs.map((doc47) => {
|
|
11784
|
+
var _a;
|
|
11785
|
+
return {
|
|
11786
|
+
id: doc47.id,
|
|
11787
|
+
email: (_a = doc47.data().basicInfo) == null ? void 0 : _a.email,
|
|
11788
|
+
status: doc47.data().status,
|
|
11789
|
+
userRef: doc47.data().userRef
|
|
11790
|
+
};
|
|
11791
|
+
})
|
|
11769
11792
|
});
|
|
11770
11793
|
return [];
|
|
11771
11794
|
}
|
|
@@ -16116,6 +16139,7 @@ var AuthService = class extends BaseService {
|
|
|
16116
16139
|
* @returns Object containing user, practitioner (if exists), and draft profiles (if any)
|
|
16117
16140
|
*/
|
|
16118
16141
|
async signUpPractitionerWithGoogle(idToken) {
|
|
16142
|
+
var _a, _b;
|
|
16119
16143
|
try {
|
|
16120
16144
|
console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
|
|
16121
16145
|
let email;
|
|
@@ -16149,12 +16173,48 @@ var AuthService = class extends BaseService {
|
|
|
16149
16173
|
console.log("[AUTH] User exists with Google provider, signing in");
|
|
16150
16174
|
const credential2 = GoogleAuthProvider.credential(idToken);
|
|
16151
16175
|
const { user: firebaseUser2 } = await signInWithCredential(this.auth, credential2);
|
|
16152
|
-
|
|
16176
|
+
let existingUser2 = null;
|
|
16177
|
+
try {
|
|
16178
|
+
existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
|
|
16179
|
+
console.log("[AUTH] User document found:", existingUser2.uid);
|
|
16180
|
+
} catch (userError) {
|
|
16181
|
+
console.log("[AUTH] User document not found in Firestore, checking for draft profiles", {
|
|
16182
|
+
errorCode: userError == null ? void 0 : userError.code,
|
|
16183
|
+
errorMessage: userError == null ? void 0 : userError.message,
|
|
16184
|
+
errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
|
|
16185
|
+
isAuthError: userError instanceof AuthError
|
|
16186
|
+
});
|
|
16187
|
+
const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
|
|
16188
|
+
const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
|
|
16189
|
+
console.log("[AUTH] Draft profiles check result:", {
|
|
16190
|
+
email: normalizedEmail,
|
|
16191
|
+
draftProfilesCount: draftProfiles3.length,
|
|
16192
|
+
draftProfileIds: draftProfiles3.map((p) => p.id)
|
|
16193
|
+
});
|
|
16194
|
+
if (draftProfiles3.length === 0) {
|
|
16195
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16196
|
+
try {
|
|
16197
|
+
await firebaseSignOut(this.auth);
|
|
16198
|
+
} catch (signOutError) {
|
|
16199
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16200
|
+
}
|
|
16201
|
+
throw new AuthError(
|
|
16202
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16203
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16204
|
+
404
|
|
16205
|
+
);
|
|
16206
|
+
}
|
|
16207
|
+
console.log("[AUTH] Draft profiles found, creating user document");
|
|
16208
|
+
existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
|
|
16209
|
+
skipProfileCreation: true
|
|
16210
|
+
});
|
|
16211
|
+
console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
|
|
16212
|
+
}
|
|
16153
16213
|
if (!existingUser2) {
|
|
16154
16214
|
await firebaseSignOut(this.auth);
|
|
16155
16215
|
throw new AuthError(
|
|
16156
|
-
"No
|
|
16157
|
-
"AUTH/
|
|
16216
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16217
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16158
16218
|
404
|
|
16159
16219
|
);
|
|
16160
16220
|
}
|
|
@@ -16204,16 +16264,47 @@ var AuthService = class extends BaseService {
|
|
|
16204
16264
|
console.error("[AUTH] Error checking for existing user:", error);
|
|
16205
16265
|
}
|
|
16206
16266
|
console.log("[AUTH] Checking for draft profiles");
|
|
16207
|
-
|
|
16267
|
+
let draftProfiles = [];
|
|
16268
|
+
try {
|
|
16269
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
16270
|
+
console.log("[AUTH] Draft profiles check complete", { count: draftProfiles.length });
|
|
16271
|
+
} catch (draftCheckError) {
|
|
16272
|
+
console.error("[AUTH] Error checking draft profiles:", draftCheckError);
|
|
16273
|
+
try {
|
|
16274
|
+
await firebaseSignOut(this.auth);
|
|
16275
|
+
} catch (signOutError) {
|
|
16276
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16277
|
+
}
|
|
16278
|
+
throw new AuthError(
|
|
16279
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16280
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16281
|
+
404
|
|
16282
|
+
);
|
|
16283
|
+
}
|
|
16208
16284
|
let user;
|
|
16209
16285
|
if (existingUser) {
|
|
16210
16286
|
user = existingUser;
|
|
16211
16287
|
console.log("[AUTH] Using existing user account");
|
|
16212
16288
|
} else {
|
|
16289
|
+
if (draftProfiles.length === 0) {
|
|
16290
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16291
|
+
try {
|
|
16292
|
+
await firebaseSignOut(this.auth);
|
|
16293
|
+
} catch (signOutError) {
|
|
16294
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16295
|
+
}
|
|
16296
|
+
const noDraftError = new AuthError(
|
|
16297
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16298
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16299
|
+
404
|
|
16300
|
+
);
|
|
16301
|
+
console.log("[AUTH] Throwing NO_DRAFT_PROFILES error:", noDraftError.code);
|
|
16302
|
+
throw noDraftError;
|
|
16303
|
+
}
|
|
16213
16304
|
user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
|
|
16214
16305
|
skipProfileCreation: true
|
|
16215
16306
|
});
|
|
16216
|
-
console.log("[AUTH] Created new user account");
|
|
16307
|
+
console.log("[AUTH] Created new user account with draft profiles available");
|
|
16217
16308
|
}
|
|
16218
16309
|
let practitioner = null;
|
|
16219
16310
|
if (user.practitionerProfile) {
|
|
@@ -16231,10 +16322,33 @@ var AuthService = class extends BaseService {
|
|
|
16231
16322
|
};
|
|
16232
16323
|
} catch (error) {
|
|
16233
16324
|
console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
|
|
16325
|
+
console.error("[AUTH] Error type:", (_b = error == null ? void 0 : error.constructor) == null ? void 0 : _b.name);
|
|
16326
|
+
console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
|
|
16327
|
+
console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
|
|
16328
|
+
console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
|
|
16234
16329
|
if (error instanceof AuthError) {
|
|
16330
|
+
console.log("[AUTH] Preserving AuthError:", error.code);
|
|
16235
16331
|
throw error;
|
|
16236
16332
|
}
|
|
16237
|
-
|
|
16333
|
+
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "";
|
|
16334
|
+
if (errorMessage.includes("NO_DRAFT_PROFILES") || errorMessage.includes("clinic invitation")) {
|
|
16335
|
+
console.log("[AUTH] Detected clinic invitation error in message, converting to AuthError");
|
|
16336
|
+
throw new AuthError(
|
|
16337
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16338
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16339
|
+
404
|
|
16340
|
+
);
|
|
16341
|
+
}
|
|
16342
|
+
const wrappedError = handleFirebaseError(error);
|
|
16343
|
+
console.log("[AUTH] Wrapped error:", wrappedError.message);
|
|
16344
|
+
if (wrappedError.message.includes("permissions") || wrappedError.message.includes("Account creation failed")) {
|
|
16345
|
+
throw new AuthError(
|
|
16346
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16347
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16348
|
+
404
|
|
16349
|
+
);
|
|
16350
|
+
}
|
|
16351
|
+
throw wrappedError;
|
|
16238
16352
|
}
|
|
16239
16353
|
}
|
|
16240
16354
|
/**
|
package/package.json
CHANGED
|
@@ -1061,12 +1061,57 @@ export class AuthService extends BaseService {
|
|
|
1061
1061
|
const credential = GoogleAuthProvider.credential(idToken);
|
|
1062
1062
|
const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
|
|
1063
1063
|
|
|
1064
|
-
|
|
1064
|
+
let existingUser: User | null = null;
|
|
1065
|
+
try {
|
|
1066
|
+
existingUser = await this.userService.getUserById(firebaseUser.uid);
|
|
1067
|
+
console.log('[AUTH] User document found:', existingUser.uid);
|
|
1068
|
+
} catch (userError: any) {
|
|
1069
|
+
// User document doesn't exist in Firestore
|
|
1070
|
+
console.log('[AUTH] User document not found in Firestore, checking for draft profiles', {
|
|
1071
|
+
errorCode: userError?.code,
|
|
1072
|
+
errorMessage: userError?.message,
|
|
1073
|
+
errorType: userError?.constructor?.name,
|
|
1074
|
+
isAuthError: userError instanceof AuthError,
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// Check for draft profiles before signing out
|
|
1078
|
+
const practitionerService = new PractitionerService(this.db, this.auth, this.app);
|
|
1079
|
+
const draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
1080
|
+
|
|
1081
|
+
console.log('[AUTH] Draft profiles check result:', {
|
|
1082
|
+
email: normalizedEmail,
|
|
1083
|
+
draftProfilesCount: draftProfiles.length,
|
|
1084
|
+
draftProfileIds: draftProfiles.map(p => p.id),
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
if (draftProfiles.length === 0) {
|
|
1088
|
+
// No draft profiles - sign out and throw error
|
|
1089
|
+
console.log('[AUTH] No draft profiles found, signing out and throwing error');
|
|
1090
|
+
try {
|
|
1091
|
+
await firebaseSignOut(this.auth);
|
|
1092
|
+
} catch (signOutError) {
|
|
1093
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1094
|
+
}
|
|
1095
|
+
throw new AuthError(
|
|
1096
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1097
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1098
|
+
404,
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// Draft profiles exist - create user document and continue
|
|
1103
|
+
console.log('[AUTH] Draft profiles found, creating user document');
|
|
1104
|
+
existingUser = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
|
|
1105
|
+
skipProfileCreation: true,
|
|
1106
|
+
});
|
|
1107
|
+
console.log('[AUTH] Created user document for existing Firebase user with draft profiles:', existingUser.uid);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1065
1110
|
if (!existingUser) {
|
|
1066
1111
|
await firebaseSignOut(this.auth);
|
|
1067
1112
|
throw new AuthError(
|
|
1068
|
-
'No
|
|
1069
|
-
'AUTH/
|
|
1113
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1114
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1070
1115
|
404,
|
|
1071
1116
|
);
|
|
1072
1117
|
}
|
|
@@ -1134,7 +1179,24 @@ export class AuthService extends BaseService {
|
|
|
1134
1179
|
|
|
1135
1180
|
// Check for draft profiles
|
|
1136
1181
|
console.log('[AUTH] Checking for draft profiles');
|
|
1137
|
-
|
|
1182
|
+
let draftProfiles: Practitioner[] = [];
|
|
1183
|
+
try {
|
|
1184
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
1185
|
+
console.log('[AUTH] Draft profiles check complete', { count: draftProfiles.length });
|
|
1186
|
+
} catch (draftCheckError: any) {
|
|
1187
|
+
console.error('[AUTH] Error checking draft profiles:', draftCheckError);
|
|
1188
|
+
// If checking draft profiles fails, sign out and throw appropriate error
|
|
1189
|
+
try {
|
|
1190
|
+
await firebaseSignOut(this.auth);
|
|
1191
|
+
} catch (signOutError) {
|
|
1192
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1193
|
+
}
|
|
1194
|
+
throw new AuthError(
|
|
1195
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1196
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1197
|
+
404,
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1138
1200
|
|
|
1139
1201
|
let user: User;
|
|
1140
1202
|
if (existingUser) {
|
|
@@ -1142,11 +1204,32 @@ export class AuthService extends BaseService {
|
|
|
1142
1204
|
user = existingUser;
|
|
1143
1205
|
console.log('[AUTH] Using existing user account');
|
|
1144
1206
|
} else {
|
|
1145
|
-
//
|
|
1207
|
+
// For new users: Only create account if there are draft profiles OR if user already has a practitioner profile
|
|
1208
|
+
// Since doctors can only join via clinic invitation, we should not create accounts without invitations
|
|
1209
|
+
if (draftProfiles.length === 0) {
|
|
1210
|
+
console.log('[AUTH] No draft profiles found, signing out and throwing error');
|
|
1211
|
+
// Sign out the Firebase user since we're not creating an account
|
|
1212
|
+
// Wrap in try-catch to handle any sign-out errors gracefully
|
|
1213
|
+
try {
|
|
1214
|
+
await firebaseSignOut(this.auth);
|
|
1215
|
+
} catch (signOutError) {
|
|
1216
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1217
|
+
// Continue anyway - the important part is we're not creating the account
|
|
1218
|
+
}
|
|
1219
|
+
const noDraftError = new AuthError(
|
|
1220
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1221
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1222
|
+
404,
|
|
1223
|
+
);
|
|
1224
|
+
console.log('[AUTH] Throwing NO_DRAFT_PROFILES error:', noDraftError.code);
|
|
1225
|
+
throw noDraftError;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// Create new user document only if draft profiles exist
|
|
1146
1229
|
user = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
|
|
1147
1230
|
skipProfileCreation: true,
|
|
1148
1231
|
});
|
|
1149
|
-
console.log('[AUTH] Created new user account');
|
|
1232
|
+
console.log('[AUTH] Created new user account with draft profiles available');
|
|
1150
1233
|
}
|
|
1151
1234
|
|
|
1152
1235
|
// Check if user already has practitioner profile
|
|
@@ -1166,12 +1249,46 @@ export class AuthService extends BaseService {
|
|
|
1166
1249
|
practitioner,
|
|
1167
1250
|
draftProfiles,
|
|
1168
1251
|
};
|
|
1169
|
-
} catch (error) {
|
|
1252
|
+
} catch (error: any) {
|
|
1170
1253
|
console.error('[AUTH] Error in signUpPractitionerWithGoogle:', error);
|
|
1254
|
+
console.error('[AUTH] Error type:', error?.constructor?.name);
|
|
1255
|
+
console.error('[AUTH] Error instanceof AuthError:', error instanceof AuthError);
|
|
1256
|
+
console.error('[AUTH] Error code:', error?.code);
|
|
1257
|
+
console.error('[AUTH] Error message:', error?.message);
|
|
1258
|
+
|
|
1259
|
+
// Preserve AuthError instances (like NO_DRAFT_PROFILES) without wrapping
|
|
1171
1260
|
if (error instanceof AuthError) {
|
|
1261
|
+
console.log('[AUTH] Preserving AuthError:', error.code);
|
|
1172
1262
|
throw error;
|
|
1173
1263
|
}
|
|
1174
|
-
|
|
1264
|
+
|
|
1265
|
+
// Check if error message contains NO_DRAFT_PROFILES before wrapping
|
|
1266
|
+
const errorMessage = error?.message || error?.toString() || '';
|
|
1267
|
+
if (errorMessage.includes('NO_DRAFT_PROFILES') || errorMessage.includes('clinic invitation')) {
|
|
1268
|
+
console.log('[AUTH] Detected clinic invitation error in message, converting to AuthError');
|
|
1269
|
+
throw new AuthError(
|
|
1270
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1271
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1272
|
+
404,
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
// For other errors, wrap them but preserve the original message if it's helpful
|
|
1277
|
+
const wrappedError = handleFirebaseError(error);
|
|
1278
|
+
console.log('[AUTH] Wrapped error:', wrappedError.message);
|
|
1279
|
+
|
|
1280
|
+
// If the wrapped error message is generic, try to preserve more context
|
|
1281
|
+
if (wrappedError.message.includes('permissions') || wrappedError.message.includes('Account creation failed')) {
|
|
1282
|
+
// This might be a permissions error during sign-out or user creation
|
|
1283
|
+
// If we got here and there were no draft profiles, it's likely the same issue
|
|
1284
|
+
throw new AuthError(
|
|
1285
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1286
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1287
|
+
404,
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
throw wrappedError;
|
|
1175
1292
|
}
|
|
1176
1293
|
}
|
|
1177
1294
|
|
|
@@ -158,6 +158,11 @@ export class PractitionerService extends BaseService {
|
|
|
158
158
|
): Promise<PractitionerBasicInfo> {
|
|
159
159
|
const processedBasicInfo = { ...basicInfo };
|
|
160
160
|
|
|
161
|
+
// Normalize email to lowercase to ensure consistent matching
|
|
162
|
+
if (processedBasicInfo.email) {
|
|
163
|
+
processedBasicInfo.email = processedBasicInfo.email.toLowerCase().trim();
|
|
164
|
+
}
|
|
165
|
+
|
|
161
166
|
// Handle profile photo upload if needed
|
|
162
167
|
if (basicInfo.profileImageUrl) {
|
|
163
168
|
const uploadedUrl = await this.handleProfilePhotoUpload(
|
|
@@ -734,6 +739,7 @@ export class PractitionerService extends BaseService {
|
|
|
734
739
|
|
|
735
740
|
console.log("[PRACTITIONER] Searching for all draft practitioners by email", {
|
|
736
741
|
email: normalizedEmail,
|
|
742
|
+
originalEmail: email,
|
|
737
743
|
});
|
|
738
744
|
|
|
739
745
|
const q = query(
|
|
@@ -748,7 +754,26 @@ export class PractitionerService extends BaseService {
|
|
|
748
754
|
if (querySnapshot.empty) {
|
|
749
755
|
console.log("[PRACTITIONER] No draft practitioners found for email", {
|
|
750
756
|
email: normalizedEmail,
|
|
757
|
+
originalEmail: email,
|
|
751
758
|
});
|
|
759
|
+
|
|
760
|
+
// Debug: Try to find ANY practitioners with this email (regardless of status)
|
|
761
|
+
const debugQ = query(
|
|
762
|
+
collection(this.db, PRACTITIONERS_COLLECTION),
|
|
763
|
+
where("basicInfo.email", "==", normalizedEmail),
|
|
764
|
+
limit(5)
|
|
765
|
+
);
|
|
766
|
+
const debugSnapshot = await getDocs(debugQ);
|
|
767
|
+
console.log("[PRACTITIONER] Debug: Found practitioners with this email (any status):", {
|
|
768
|
+
count: debugSnapshot.size,
|
|
769
|
+
practitioners: debugSnapshot.docs.map(doc => ({
|
|
770
|
+
id: doc.id,
|
|
771
|
+
email: doc.data().basicInfo?.email,
|
|
772
|
+
status: doc.data().status,
|
|
773
|
+
userRef: doc.data().userRef,
|
|
774
|
+
})),
|
|
775
|
+
});
|
|
776
|
+
|
|
752
777
|
return [];
|
|
753
778
|
}
|
|
754
779
|
|