@blackcode_sa/metaestetics-api 1.14.0 → 1.14.2
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +141 -8
- package/dist/index.mjs +141 -8
- package/package.json +1 -1
- package/src/services/auth/auth.service.ts +150 -9
- package/src/services/practitioner/practitioner.service.ts +25 -0
package/dist/index.d.mts
CHANGED
|
@@ -8443,7 +8443,7 @@ declare class AuthService extends BaseService {
|
|
|
8443
8443
|
* @returns Object containing user, practitioner (if exists), and draft profiles (if any)
|
|
8444
8444
|
*/
|
|
8445
8445
|
signUpPractitionerWithGoogle(idToken: string): Promise<{
|
|
8446
|
-
user: User;
|
|
8446
|
+
user: User | null;
|
|
8447
8447
|
practitioner: Practitioner | null;
|
|
8448
8448
|
draftProfiles: Practitioner[];
|
|
8449
8449
|
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -8443,7 +8443,7 @@ declare class AuthService extends BaseService {
|
|
|
8443
8443
|
* @returns Object containing user, practitioner (if exists), and draft profiles (if any)
|
|
8444
8444
|
*/
|
|
8445
8445
|
signUpPractitionerWithGoogle(idToken: string): Promise<{
|
|
8446
|
-
user: User;
|
|
8446
|
+
user: User | null;
|
|
8447
8447
|
practitioner: Practitioner | null;
|
|
8448
8448
|
draftProfiles: Practitioner[];
|
|
8449
8449
|
}>;
|
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,67 @@ 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, attempting to create user document");
|
|
16121
|
+
const draftProfilesFound = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
|
|
16122
|
+
try {
|
|
16123
|
+
existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
|
|
16124
|
+
skipProfileCreation: true
|
|
16125
|
+
});
|
|
16126
|
+
console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
|
|
16127
|
+
} catch (createError) {
|
|
16128
|
+
console.error("[AUTH] Error creating user document:", {
|
|
16129
|
+
error: createError,
|
|
16130
|
+
code: createError == null ? void 0 : createError.code,
|
|
16131
|
+
message: createError == null ? void 0 : createError.message
|
|
16132
|
+
});
|
|
16133
|
+
try {
|
|
16134
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16135
|
+
} catch (signOutError) {
|
|
16136
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16137
|
+
}
|
|
16138
|
+
throw new AuthError(
|
|
16139
|
+
"Unable to create account. Please use the token provided by your clinic to register, or contact support.",
|
|
16140
|
+
"AUTH/USER_CREATION_FAILED",
|
|
16141
|
+
500
|
|
16142
|
+
);
|
|
16143
|
+
}
|
|
16144
|
+
}
|
|
16066
16145
|
if (!existingUser2) {
|
|
16067
16146
|
await (0, import_auth8.signOut)(this.auth);
|
|
16068
16147
|
throw new AuthError(
|
|
16069
|
-
"No
|
|
16070
|
-
"AUTH/
|
|
16148
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16149
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16071
16150
|
404
|
|
16072
16151
|
);
|
|
16073
16152
|
}
|
|
@@ -16117,16 +16196,47 @@ var AuthService = class extends BaseService {
|
|
|
16117
16196
|
console.error("[AUTH] Error checking for existing user:", error);
|
|
16118
16197
|
}
|
|
16119
16198
|
console.log("[AUTH] Checking for draft profiles");
|
|
16120
|
-
|
|
16199
|
+
let draftProfiles = [];
|
|
16200
|
+
try {
|
|
16201
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
16202
|
+
console.log("[AUTH] Draft profiles check complete", { count: draftProfiles.length });
|
|
16203
|
+
} catch (draftCheckError) {
|
|
16204
|
+
console.error("[AUTH] Error checking draft profiles:", draftCheckError);
|
|
16205
|
+
try {
|
|
16206
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16207
|
+
} catch (signOutError) {
|
|
16208
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16209
|
+
}
|
|
16210
|
+
throw new AuthError(
|
|
16211
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16212
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16213
|
+
404
|
|
16214
|
+
);
|
|
16215
|
+
}
|
|
16121
16216
|
let user;
|
|
16122
16217
|
if (existingUser) {
|
|
16123
16218
|
user = existingUser;
|
|
16124
16219
|
console.log("[AUTH] Using existing user account");
|
|
16125
16220
|
} else {
|
|
16221
|
+
if (draftProfiles.length === 0) {
|
|
16222
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16223
|
+
try {
|
|
16224
|
+
await (0, import_auth8.signOut)(this.auth);
|
|
16225
|
+
} catch (signOutError) {
|
|
16226
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16227
|
+
}
|
|
16228
|
+
const noDraftError = new AuthError(
|
|
16229
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16230
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16231
|
+
404
|
|
16232
|
+
);
|
|
16233
|
+
console.log("[AUTH] Throwing NO_DRAFT_PROFILES error:", noDraftError.code);
|
|
16234
|
+
throw noDraftError;
|
|
16235
|
+
}
|
|
16126
16236
|
user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
|
|
16127
16237
|
skipProfileCreation: true
|
|
16128
16238
|
});
|
|
16129
|
-
console.log("[AUTH] Created new user account");
|
|
16239
|
+
console.log("[AUTH] Created new user account with draft profiles available");
|
|
16130
16240
|
}
|
|
16131
16241
|
let practitioner = null;
|
|
16132
16242
|
if (user.practitionerProfile) {
|
|
@@ -16144,10 +16254,33 @@ var AuthService = class extends BaseService {
|
|
|
16144
16254
|
};
|
|
16145
16255
|
} catch (error) {
|
|
16146
16256
|
console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
|
|
16257
|
+
console.error("[AUTH] Error type:", (_b = error == null ? void 0 : error.constructor) == null ? void 0 : _b.name);
|
|
16258
|
+
console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
|
|
16259
|
+
console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
|
|
16260
|
+
console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
|
|
16147
16261
|
if (error instanceof AuthError) {
|
|
16262
|
+
console.log("[AUTH] Preserving AuthError:", error.code);
|
|
16148
16263
|
throw error;
|
|
16149
16264
|
}
|
|
16150
|
-
|
|
16265
|
+
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "";
|
|
16266
|
+
if (errorMessage.includes("NO_DRAFT_PROFILES") || errorMessage.includes("clinic invitation")) {
|
|
16267
|
+
console.log("[AUTH] Detected clinic invitation error in message, converting to AuthError");
|
|
16268
|
+
throw new AuthError(
|
|
16269
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16270
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16271
|
+
404
|
|
16272
|
+
);
|
|
16273
|
+
}
|
|
16274
|
+
const wrappedError = handleFirebaseError(error);
|
|
16275
|
+
console.log("[AUTH] Wrapped error:", wrappedError.message);
|
|
16276
|
+
if (wrappedError.message.includes("permissions") || wrappedError.message.includes("Account creation failed")) {
|
|
16277
|
+
throw new AuthError(
|
|
16278
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16279
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16280
|
+
404
|
|
16281
|
+
);
|
|
16282
|
+
}
|
|
16283
|
+
throw wrappedError;
|
|
16151
16284
|
}
|
|
16152
16285
|
}
|
|
16153
16286
|
/**
|
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,67 @@ 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, attempting to create user document");
|
|
16208
|
+
const draftProfilesFound = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
|
|
16209
|
+
try {
|
|
16210
|
+
existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
|
|
16211
|
+
skipProfileCreation: true
|
|
16212
|
+
});
|
|
16213
|
+
console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
|
|
16214
|
+
} catch (createError) {
|
|
16215
|
+
console.error("[AUTH] Error creating user document:", {
|
|
16216
|
+
error: createError,
|
|
16217
|
+
code: createError == null ? void 0 : createError.code,
|
|
16218
|
+
message: createError == null ? void 0 : createError.message
|
|
16219
|
+
});
|
|
16220
|
+
try {
|
|
16221
|
+
await firebaseSignOut(this.auth);
|
|
16222
|
+
} catch (signOutError) {
|
|
16223
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16224
|
+
}
|
|
16225
|
+
throw new AuthError(
|
|
16226
|
+
"Unable to create account. Please use the token provided by your clinic to register, or contact support.",
|
|
16227
|
+
"AUTH/USER_CREATION_FAILED",
|
|
16228
|
+
500
|
|
16229
|
+
);
|
|
16230
|
+
}
|
|
16231
|
+
}
|
|
16153
16232
|
if (!existingUser2) {
|
|
16154
16233
|
await firebaseSignOut(this.auth);
|
|
16155
16234
|
throw new AuthError(
|
|
16156
|
-
"No
|
|
16157
|
-
"AUTH/
|
|
16235
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16236
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16158
16237
|
404
|
|
16159
16238
|
);
|
|
16160
16239
|
}
|
|
@@ -16204,16 +16283,47 @@ var AuthService = class extends BaseService {
|
|
|
16204
16283
|
console.error("[AUTH] Error checking for existing user:", error);
|
|
16205
16284
|
}
|
|
16206
16285
|
console.log("[AUTH] Checking for draft profiles");
|
|
16207
|
-
|
|
16286
|
+
let draftProfiles = [];
|
|
16287
|
+
try {
|
|
16288
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
16289
|
+
console.log("[AUTH] Draft profiles check complete", { count: draftProfiles.length });
|
|
16290
|
+
} catch (draftCheckError) {
|
|
16291
|
+
console.error("[AUTH] Error checking draft profiles:", draftCheckError);
|
|
16292
|
+
try {
|
|
16293
|
+
await firebaseSignOut(this.auth);
|
|
16294
|
+
} catch (signOutError) {
|
|
16295
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16296
|
+
}
|
|
16297
|
+
throw new AuthError(
|
|
16298
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16299
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16300
|
+
404
|
|
16301
|
+
);
|
|
16302
|
+
}
|
|
16208
16303
|
let user;
|
|
16209
16304
|
if (existingUser) {
|
|
16210
16305
|
user = existingUser;
|
|
16211
16306
|
console.log("[AUTH] Using existing user account");
|
|
16212
16307
|
} else {
|
|
16308
|
+
if (draftProfiles.length === 0) {
|
|
16309
|
+
console.log("[AUTH] No draft profiles found, signing out and throwing error");
|
|
16310
|
+
try {
|
|
16311
|
+
await firebaseSignOut(this.auth);
|
|
16312
|
+
} catch (signOutError) {
|
|
16313
|
+
console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
|
|
16314
|
+
}
|
|
16315
|
+
const noDraftError = new AuthError(
|
|
16316
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16317
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16318
|
+
404
|
|
16319
|
+
);
|
|
16320
|
+
console.log("[AUTH] Throwing NO_DRAFT_PROFILES error:", noDraftError.code);
|
|
16321
|
+
throw noDraftError;
|
|
16322
|
+
}
|
|
16213
16323
|
user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
|
|
16214
16324
|
skipProfileCreation: true
|
|
16215
16325
|
});
|
|
16216
|
-
console.log("[AUTH] Created new user account");
|
|
16326
|
+
console.log("[AUTH] Created new user account with draft profiles available");
|
|
16217
16327
|
}
|
|
16218
16328
|
let practitioner = null;
|
|
16219
16329
|
if (user.practitionerProfile) {
|
|
@@ -16231,10 +16341,33 @@ var AuthService = class extends BaseService {
|
|
|
16231
16341
|
};
|
|
16232
16342
|
} catch (error) {
|
|
16233
16343
|
console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
|
|
16344
|
+
console.error("[AUTH] Error type:", (_b = error == null ? void 0 : error.constructor) == null ? void 0 : _b.name);
|
|
16345
|
+
console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
|
|
16346
|
+
console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
|
|
16347
|
+
console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
|
|
16234
16348
|
if (error instanceof AuthError) {
|
|
16349
|
+
console.log("[AUTH] Preserving AuthError:", error.code);
|
|
16235
16350
|
throw error;
|
|
16236
16351
|
}
|
|
16237
|
-
|
|
16352
|
+
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.toString()) || "";
|
|
16353
|
+
if (errorMessage.includes("NO_DRAFT_PROFILES") || errorMessage.includes("clinic invitation")) {
|
|
16354
|
+
console.log("[AUTH] Detected clinic invitation error in message, converting to AuthError");
|
|
16355
|
+
throw new AuthError(
|
|
16356
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16357
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16358
|
+
404
|
|
16359
|
+
);
|
|
16360
|
+
}
|
|
16361
|
+
const wrappedError = handleFirebaseError(error);
|
|
16362
|
+
console.log("[AUTH] Wrapped error:", wrappedError.message);
|
|
16363
|
+
if (wrappedError.message.includes("permissions") || wrappedError.message.includes("Account creation failed")) {
|
|
16364
|
+
throw new AuthError(
|
|
16365
|
+
"No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.",
|
|
16366
|
+
"AUTH/NO_DRAFT_PROFILES",
|
|
16367
|
+
404
|
|
16368
|
+
);
|
|
16369
|
+
}
|
|
16370
|
+
throw wrappedError;
|
|
16238
16371
|
}
|
|
16239
16372
|
}
|
|
16240
16373
|
/**
|
package/package.json
CHANGED
|
@@ -1012,7 +1012,7 @@ export class AuthService extends BaseService {
|
|
|
1012
1012
|
async signUpPractitionerWithGoogle(
|
|
1013
1013
|
idToken: string
|
|
1014
1014
|
): Promise<{
|
|
1015
|
-
user: User;
|
|
1015
|
+
user: User | null;
|
|
1016
1016
|
practitioner: Practitioner | null;
|
|
1017
1017
|
draftProfiles: Practitioner[];
|
|
1018
1018
|
}> {
|
|
@@ -1061,12 +1061,81 @@ 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 - try to create User document
|
|
1103
|
+
// Firestore rules should allow authenticated users to create their own User document
|
|
1104
|
+
console.log('[AUTH] Draft profiles found, attempting to create user document');
|
|
1105
|
+
const draftProfilesFound = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
1106
|
+
|
|
1107
|
+
try {
|
|
1108
|
+
existingUser = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
|
|
1109
|
+
skipProfileCreation: true,
|
|
1110
|
+
});
|
|
1111
|
+
console.log('[AUTH] Created user document for existing Firebase user with draft profiles:', existingUser.uid);
|
|
1112
|
+
} catch (createError: any) {
|
|
1113
|
+
console.error('[AUTH] Error creating user document:', {
|
|
1114
|
+
error: createError,
|
|
1115
|
+
code: createError?.code,
|
|
1116
|
+
message: createError?.message,
|
|
1117
|
+
});
|
|
1118
|
+
// If creation fails, sign out and throw error
|
|
1119
|
+
// User will need to use token flow or contact support
|
|
1120
|
+
try {
|
|
1121
|
+
await firebaseSignOut(this.auth);
|
|
1122
|
+
} catch (signOutError) {
|
|
1123
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1124
|
+
}
|
|
1125
|
+
throw new AuthError(
|
|
1126
|
+
'Unable to create account. Please use the token provided by your clinic to register, or contact support.',
|
|
1127
|
+
'AUTH/USER_CREATION_FAILED',
|
|
1128
|
+
500,
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
// User document exists - check for practitioner profile and draft profiles
|
|
1065
1134
|
if (!existingUser) {
|
|
1066
1135
|
await firebaseSignOut(this.auth);
|
|
1067
1136
|
throw new AuthError(
|
|
1068
|
-
'No
|
|
1069
|
-
'AUTH/
|
|
1137
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1138
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1070
1139
|
404,
|
|
1071
1140
|
);
|
|
1072
1141
|
}
|
|
@@ -1134,7 +1203,24 @@ export class AuthService extends BaseService {
|
|
|
1134
1203
|
|
|
1135
1204
|
// Check for draft profiles
|
|
1136
1205
|
console.log('[AUTH] Checking for draft profiles');
|
|
1137
|
-
|
|
1206
|
+
let draftProfiles: Practitioner[] = [];
|
|
1207
|
+
try {
|
|
1208
|
+
draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
|
|
1209
|
+
console.log('[AUTH] Draft profiles check complete', { count: draftProfiles.length });
|
|
1210
|
+
} catch (draftCheckError: any) {
|
|
1211
|
+
console.error('[AUTH] Error checking draft profiles:', draftCheckError);
|
|
1212
|
+
// If checking draft profiles fails, sign out and throw appropriate error
|
|
1213
|
+
try {
|
|
1214
|
+
await firebaseSignOut(this.auth);
|
|
1215
|
+
} catch (signOutError) {
|
|
1216
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1217
|
+
}
|
|
1218
|
+
throw new AuthError(
|
|
1219
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1220
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1221
|
+
404,
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1138
1224
|
|
|
1139
1225
|
let user: User;
|
|
1140
1226
|
if (existingUser) {
|
|
@@ -1142,11 +1228,32 @@ export class AuthService extends BaseService {
|
|
|
1142
1228
|
user = existingUser;
|
|
1143
1229
|
console.log('[AUTH] Using existing user account');
|
|
1144
1230
|
} else {
|
|
1145
|
-
//
|
|
1231
|
+
// For new users: Only create account if there are draft profiles OR if user already has a practitioner profile
|
|
1232
|
+
// Since doctors can only join via clinic invitation, we should not create accounts without invitations
|
|
1233
|
+
if (draftProfiles.length === 0) {
|
|
1234
|
+
console.log('[AUTH] No draft profiles found, signing out and throwing error');
|
|
1235
|
+
// Sign out the Firebase user since we're not creating an account
|
|
1236
|
+
// Wrap in try-catch to handle any sign-out errors gracefully
|
|
1237
|
+
try {
|
|
1238
|
+
await firebaseSignOut(this.auth);
|
|
1239
|
+
} catch (signOutError) {
|
|
1240
|
+
console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
|
|
1241
|
+
// Continue anyway - the important part is we're not creating the account
|
|
1242
|
+
}
|
|
1243
|
+
const noDraftError = new AuthError(
|
|
1244
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1245
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1246
|
+
404,
|
|
1247
|
+
);
|
|
1248
|
+
console.log('[AUTH] Throwing NO_DRAFT_PROFILES error:', noDraftError.code);
|
|
1249
|
+
throw noDraftError;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// Create new user document only if draft profiles exist
|
|
1146
1253
|
user = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
|
|
1147
1254
|
skipProfileCreation: true,
|
|
1148
1255
|
});
|
|
1149
|
-
console.log('[AUTH] Created new user account');
|
|
1256
|
+
console.log('[AUTH] Created new user account with draft profiles available');
|
|
1150
1257
|
}
|
|
1151
1258
|
|
|
1152
1259
|
// Check if user already has practitioner profile
|
|
@@ -1166,12 +1273,46 @@ export class AuthService extends BaseService {
|
|
|
1166
1273
|
practitioner,
|
|
1167
1274
|
draftProfiles,
|
|
1168
1275
|
};
|
|
1169
|
-
} catch (error) {
|
|
1276
|
+
} catch (error: any) {
|
|
1170
1277
|
console.error('[AUTH] Error in signUpPractitionerWithGoogle:', error);
|
|
1278
|
+
console.error('[AUTH] Error type:', error?.constructor?.name);
|
|
1279
|
+
console.error('[AUTH] Error instanceof AuthError:', error instanceof AuthError);
|
|
1280
|
+
console.error('[AUTH] Error code:', error?.code);
|
|
1281
|
+
console.error('[AUTH] Error message:', error?.message);
|
|
1282
|
+
|
|
1283
|
+
// Preserve AuthError instances (like NO_DRAFT_PROFILES) without wrapping
|
|
1171
1284
|
if (error instanceof AuthError) {
|
|
1285
|
+
console.log('[AUTH] Preserving AuthError:', error.code);
|
|
1172
1286
|
throw error;
|
|
1173
1287
|
}
|
|
1174
|
-
|
|
1288
|
+
|
|
1289
|
+
// Check if error message contains NO_DRAFT_PROFILES before wrapping
|
|
1290
|
+
const errorMessage = error?.message || error?.toString() || '';
|
|
1291
|
+
if (errorMessage.includes('NO_DRAFT_PROFILES') || errorMessage.includes('clinic invitation')) {
|
|
1292
|
+
console.log('[AUTH] Detected clinic invitation error in message, converting to AuthError');
|
|
1293
|
+
throw new AuthError(
|
|
1294
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1295
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1296
|
+
404,
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
// For other errors, wrap them but preserve the original message if it's helpful
|
|
1301
|
+
const wrappedError = handleFirebaseError(error);
|
|
1302
|
+
console.log('[AUTH] Wrapped error:', wrappedError.message);
|
|
1303
|
+
|
|
1304
|
+
// If the wrapped error message is generic, try to preserve more context
|
|
1305
|
+
if (wrappedError.message.includes('permissions') || wrappedError.message.includes('Account creation failed')) {
|
|
1306
|
+
// This might be a permissions error during sign-out or user creation
|
|
1307
|
+
// If we got here and there were no draft profiles, it's likely the same issue
|
|
1308
|
+
throw new AuthError(
|
|
1309
|
+
'No clinic invitation found for this email. Please contact your clinic administrator to receive an invitation, or use the token provided by your clinic.',
|
|
1310
|
+
'AUTH/NO_DRAFT_PROFILES',
|
|
1311
|
+
404,
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
throw wrappedError;
|
|
1175
1316
|
}
|
|
1176
1317
|
}
|
|
1177
1318
|
|
|
@@ -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
|
|