feature/add-client #22

Merged
benoybose merged 32 commits from feature/add-client into dev 2025-04-21 10:59:45 +00:00
Showing only changes of commit 1f476a3071 - Show all commits

View File

@ -1,10 +1,11 @@
import { onRequest } from "firebase-functions/v2/https"; import { onRequest } from "firebase-functions/v2/https";
import { getAdmin } from "../shared/config";
import { getCorsHandler } from "../shared/middleware"; import { getCorsHandler } from "../shared/middleware";
import { getAdmin, getLogger } from "../shared/config";
const corsHandler = getCorsHandler(); const corsHandler = getCorsHandler();
const admin = getAdmin(); const admin = getAdmin();
const logger = getLogger();
export const registerClient = onRequest({ export const registerClient = onRequest({
region: '#{SERVICES_RGN}#' region: '#{SERVICES_RGN}#'
}, async (req, res) => { }, async (req, res) => {
@ -13,34 +14,51 @@ export const registerClient = onRequest({
if (req.method !== 'POST') { if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed. Please use POST.' }); return res.status(405).json({ error: 'Method not allowed. Please use POST.' });
} }
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Unauthorized. Missing or invalid authorization header.' });
}
const idToken = authHeader.split('Bearer ')[1];
try {
const decodedToken = await admin.auth().verifyIdToken(idToken);
const uid = decodedToken.uid;
const userDoc = await admin.firestore().collection('users').doc(uid).get();
if (!userDoc.exists) {
return res.status(403).json({ error: 'Forbidden. User not found.' });
}
const userData = userDoc.data();
if (!userData || !userData.roles || !userData.roles.includes('gym_owner')) {
return res.status(403).json({ error: 'Forbidden. Only gym owners can register clients.' });
}
const gymUser = req.body; const gymUser = req.body;
if (!gymUser.phoneNumber) { if (!gymUser.phoneNumber) {
return res.status(400).json({ error: 'Phone number is required' }); return res.status(400).json({ error: 'Phone number is required' });
} }
const isdCode = gymUser.isdCode || '+1'; const isdCode = gymUser.isdCode || '91';
const formattedPhoneNumber = gymUser.phoneNumber.startsWith('+') const formattedPhoneNumber = gymUser.phoneNumber.startsWith('+')
? gymUser.phoneNumber ? gymUser.phoneNumber
: `${isdCode}${gymUser.phoneNumber}`; : `${isdCode}${gymUser.phoneNumber}`;
let uid; let clientUid;
try { try {
const userRecord = await admin.auth().getUserByPhoneNumber(formattedPhoneNumber) const userRecord = await admin.auth().getUserByPhoneNumber(formattedPhoneNumber)
.catch(() => null); .catch(() => null);
if (userRecord) { if (userRecord) {
uid = userRecord.uid; clientUid = userRecord.uid;
} else { } else {
const newUser = await admin.auth().createUser({ const newUser = await admin.auth().createUser({
phoneNumber: formattedPhoneNumber, phoneNumber: formattedPhoneNumber,
displayName: gymUser.name || '', displayName: gymUser.name || '',
email: gymUser.email || null, email: gymUser.email || null,
}); });
uid = newUser.uid; clientUid = newUser.uid;
} }
} catch (error) { } catch (error) {
console.error('Error creating authentication user:', error); logger.error('Error creating authentication user:', error);
return res.status(500).json({ return res.status(500).json({
error: 'Failed to create authentication user', error: 'Failed to create authentication user',
details: error details: error
@ -48,7 +66,8 @@ export const registerClient = onRequest({
} }
try { try {
gymUser.uid = uid; gymUser.uid = clientUid;
gymUser.registeredBy = uid;
if (gymUser.name) { if (gymUser.name) {
gymUser.normalizedName = gymUser.name.toLowerCase(); gymUser.normalizedName = gymUser.name.toLowerCase();
@ -60,24 +79,25 @@ export const registerClient = onRequest({
const clientData = { const clientData = {
...gymUser, ...gymUser,
phoneNumber: formattedPhoneNumber,
}; };
await admin.firestore().collection('client_profile').doc(uid).set(clientData); await admin.firestore().collection('client_profile').doc(clientUid).set(clientData);
return res.status(201).json({ return res.status(201).json({
success: true, success: true,
message: 'Client registered successfully', message: 'Client registered successfully',
clientId: uid clientId: clientUid
}); });
} catch (error) { } catch (error) {
console.error('Error creating client profile:', error); logger.error('Error creating client profile:', error);
try { try {
if (!gymUser.uid) { if (!gymUser.uid) {
await admin.auth().deleteUser(uid); await admin.auth().deleteUser(clientUid);
} }
} catch (deleteError) { } catch (deleteError) {
console.error('Error deleting auth user after failed profile creation:', deleteError); logger.error('Error deleting auth user after failed profile creation:', deleteError);
} }
return res.status(500).json({ return res.status(500).json({
@ -85,8 +105,13 @@ export const registerClient = onRequest({
details: error details: error
}); });
} }
} catch (authError) {
logger.error('Authentication error:', authError);
return res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
} catch (error) { } catch (error) {
console.error('Unexpected error in client registration:', error); logger.error('Unexpected error in client registration:', error);
return res.status(500).json({ return res.status(500).json({
error: 'Internal server error', error: 'Internal server error',
details: error details: error