diff --git a/functions/src/clientRegistration/clientRegistration.ts b/functions/src/clientRegistration/clientRegistration.ts index 08dbe19..8ed51fb 100644 --- a/functions/src/clientRegistration/clientRegistration.ts +++ b/functions/src/clientRegistration/clientRegistration.ts @@ -1,10 +1,11 @@ import { onRequest } from "firebase-functions/v2/https"; -import { getAdmin } from "../shared/config"; import { getCorsHandler } from "../shared/middleware"; - +import { getAdmin, getLogger } from "../shared/config"; const corsHandler = getCorsHandler(); const admin = getAdmin(); +const logger = getLogger(); + export const registerClient = onRequest({ region: '#{SERVICES_RGN}#' }, async (req, res) => { @@ -13,80 +14,104 @@ export const registerClient = onRequest({ if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed. Please use POST.' }); } - - const gymUser = req.body; - if (!gymUser.phoneNumber) { - return res.status(400).json({ error: 'Phone number is required' }); + const authHeader = req.headers.authorization; + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json({ error: 'Unauthorized. Missing or invalid authorization header.' }); } - - const isdCode = gymUser.isdCode || '+1'; - const formattedPhoneNumber = gymUser.phoneNumber.startsWith('+') - ? gymUser.phoneNumber - : `${isdCode}${gymUser.phoneNumber}`; - - let uid; + const idToken = authHeader.split('Bearer ')[1]; try { - const userRecord = await admin.auth().getUserByPhoneNumber(formattedPhoneNumber) - .catch(() => null); + const decodedToken = await admin.auth().verifyIdToken(idToken); + const uid = decodedToken.uid; + const userDoc = await admin.firestore().collection('users').doc(uid).get(); - if (userRecord) { - uid = userRecord.uid; - } else { - const newUser = await admin.auth().createUser({ - phoneNumber: formattedPhoneNumber, - displayName: gymUser.name || '', - email: gymUser.email || null, + 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; + if (!gymUser.phoneNumber) { + return res.status(400).json({ error: 'Phone number is required' }); + } + + const isdCode = gymUser.isdCode || '91'; + const formattedPhoneNumber = gymUser.phoneNumber.startsWith('+') + ? gymUser.phoneNumber + : `${isdCode}${gymUser.phoneNumber}`; + + let clientUid; + try { + const userRecord = await admin.auth().getUserByPhoneNumber(formattedPhoneNumber) + .catch(() => null); + + if (userRecord) { + clientUid = userRecord.uid; + } else { + const newUser = await admin.auth().createUser({ + phoneNumber: formattedPhoneNumber, + displayName: gymUser.name || '', + email: gymUser.email || null, + }); + clientUid = newUser.uid; + } + } catch (error) { + logger.error('Error creating authentication user:', error); + return res.status(500).json({ + error: 'Failed to create authentication user', + details: error }); - uid = newUser.uid; } - } catch (error) { - console.error('Error creating authentication user:', error); - return res.status(500).json({ - error: 'Failed to create authentication user', - details: error - }); - } - - try { - gymUser.uid = uid; - - if (gymUser.name) { - gymUser.normalizedName = gymUser.name.toLowerCase(); - } - - if (gymUser.dateOfBirth && !(typeof gymUser.dateOfBirth === 'string')) { - gymUser.dateOfBirth = new Date(gymUser.dateOfBirth).toISOString(); - } - - const clientData = { - ...gymUser, - }; - - await admin.firestore().collection('client_profile').doc(uid).set(clientData); - - return res.status(201).json({ - success: true, - message: 'Client registered successfully', - clientId: uid - }); - } catch (error) { - console.error('Error creating client profile:', error); try { - if (!gymUser.uid) { - await admin.auth().deleteUser(uid); + gymUser.uid = clientUid; + gymUser.registeredBy = uid; + + if (gymUser.name) { + gymUser.normalizedName = gymUser.name.toLowerCase(); } - } catch (deleteError) { - console.error('Error deleting auth user after failed profile creation:', deleteError); + + if (gymUser.dateOfBirth && !(typeof gymUser.dateOfBirth === 'string')) { + gymUser.dateOfBirth = new Date(gymUser.dateOfBirth).toISOString(); + } + + const clientData = { + ...gymUser, + phoneNumber: formattedPhoneNumber, + }; + + await admin.firestore().collection('client_profile').doc(clientUid).set(clientData); + + return res.status(201).json({ + success: true, + message: 'Client registered successfully', + clientId: clientUid + }); + } catch (error) { + logger.error('Error creating client profile:', error); + + try { + if (!gymUser.uid) { + await admin.auth().deleteUser(clientUid); + } + } catch (deleteError) { + logger.error('Error deleting auth user after failed profile creation:', deleteError); + } + + return res.status(500).json({ + error: 'Failed to create client profile', + details: error + }); } - return res.status(500).json({ - error: 'Failed to create client profile', - details: error - }); + } catch (authError) { + logger.error('Authentication error:', authError); + return res.status(401).json({ error: 'Unauthorized. Invalid token.' }); } } catch (error) { - console.error('Unexpected error in client registration:', error); + logger.error('Unexpected error in client registration:', error); return res.status(500).json({ error: 'Internal server error', details: error