Prashikshak / App /src /services /AuthService.js
Abhisingh-18's picture
Initial commit: Prashikshak - disaster management training platform
9a92a42
Raw
History Blame Contribute Delete
11.5 kB
// Real API service for authentication with backend
import AsyncStorage from '@react-native-async-storage/async-storage';
class AuthService {
constructor() {
// Use centralized config for API base URL
try {
const { API_BASE_URL } = require('./config');
this.baseURL = API_BASE_URL;
} catch (e) {
this.baseURL = 'http://192.168.1.8:5000'; // fallback
}
this.isRefreshing = false;
this.failedQueue = [];
}
// Process queue of failed requests after token refresh
processQueue(error, token = null) {
this.failedQueue.forEach(prom => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
this.failedQueue = [];
}
// Get stored access token
async getAccessToken() {
try {
// 1. Check NEW system token first (authToken)
const authToken = await AsyncStorage.getItem('authToken');
if (authToken) {
// console.log('🔑 AuthService: Using authToken (New System)');
return authToken;
}
// 2. Fallback to OLD system token (accessToken)
const token = await AsyncStorage.getItem('accessToken');
if (token) {
// console.log('🔑 AuthService: Using accessToken (Legacy)');
return token;
}
console.log('⚠️ AuthService: No token found');
return null;
} catch (error) {
console.error('Error getting access token:', error);
return null;
}
}
// Get stored refresh token
async getRefreshToken() {
try {
return await AsyncStorage.getItem('refreshToken');
} catch (error) {
console.error('Error getting refresh token:', error);
return null;
}
}
// Save tokens to AsyncStorage
async saveTokens(accessToken, refreshToken) {
try {
await AsyncStorage.setItem('accessToken', accessToken);
await AsyncStorage.setItem('refreshToken', refreshToken);
console.log('✅ Tokens saved to AsyncStorage');
} catch (error) {
console.error('❌ Error saving tokens:', error);
}
}
// Refresh access token using refresh token
async refreshAccessToken() {
// The new backend system currently handles session expiration via re-login
// There is no explicit refresh token flow in the current router inspection
console.log('⚠️ Token refresh not supported in new backend. Forcing logout.');
await this.clearTokens();
throw new Error('Session expired. Please login again.');
}
// Make authenticated API call with automatic token refresh
async authenticatedFetch(url, options = {}) {
let accessToken = await this.getAccessToken();
if (!accessToken) {
throw new Error('No access token available. Please login.');
}
// Add authorization header
const headers = {
...options.headers,
'Authorization': `Bearer ${accessToken}`,
};
let response = await fetch(url, { ...options, headers });
// If unauthorized, try to refresh token
if (response.status === 401) {
if (!this.isRefreshing) {
this.isRefreshing = true;
try {
accessToken = await this.refreshAccessToken();
this.isRefreshing = false;
this.processQueue(null, accessToken);
} catch (error) {
this.isRefreshing = false;
this.processQueue(error, null);
throw error;
}
}
// Retry the request with new token
return new Promise((resolve, reject) => {
this.failedQueue.push({ resolve, reject });
}).then(token => {
headers['Authorization'] = `Bearer ${token}`;
return fetch(url, { ...options, headers });
});
}
return response;
}
// Clear all stored tokens
async clearTokens() {
try {
await AsyncStorage.removeItem('accessToken');
await AsyncStorage.removeItem('refreshToken');
await AsyncStorage.removeItem('token'); // Old token key
await AsyncStorage.removeItem('authToken'); // New token key
console.log('✅ Tokens cleared');
} catch (error) {
console.error('❌ Error clearing tokens:', error);
}
}
// Real authentication with backend API
async authenticateUser(email, password) {
try {
console.log('🔐 Authenticating user with backend:', email);
const response = await fetch(`${this.baseURL}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});
const data = await response.json();
if (response.ok && data.success) {
console.log('✅ Authentication successful for:', email);
// Save both tokens
await this.saveTokens(data.accessToken, data.refreshToken);
// Save user data
await AsyncStorage.setItem('userData', JSON.stringify(data.user));
return {
success: true,
user: data.user,
accessToken: data.accessToken,
refreshToken: data.refreshToken
};
} else {
console.log('❌ Authentication failed:', data.error);
return {
success: false,
error: data.error || 'Authentication failed'
};
}
} catch (error) {
console.error('❌ Authentication error:', error);
return {
success: false,
error: error.message
};
}
}
// Real registration with backend API
async registerUser(userData, userType) {
try {
console.log('📝 Registering user with backend:', userData.email, 'Type:', userType);
const registerData = {
name: userData.name,
email: userData.email,
password: userData.password,
role: userType === 'central_authority' ? 'authority' : 'trainer'
};
const response = await fetch(`${this.baseURL}/api/auth/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(registerData),
});
const data = await response.json();
if (response.ok && data.success) {
console.log('✅ Registration successful for:', userData.email);
// Save both tokens
await this.saveTokens(data.accessToken, data.refreshToken);
// Save user data
await AsyncStorage.setItem('userData', JSON.stringify(data.user));
return {
success: true,
user: data.user,
message: 'Registration successful! You can now login.'
};
} else {
console.log('❌ Registration failed:', data.error);
return {
success: false,
error: data.error || 'Registration failed'
};
}
} catch (error) {
console.error('❌ Registration error:', error);
return {
success: false,
error: error.message
};
}
}
// Get user profile
async getUserProfile(userId, token) {
try {
// Simulate API call
await this.delay(1000);
// Mock user profile data
return {
success: true,
user: {
id: userId,
name: 'Demo User',
email: 'demo@ndma.gov.in',
type: 'general',
verified: true,
lastLogin: new Date().toISOString()
}
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Update user profile
async updateUserProfile(userId, updateData, token) {
try {
await this.delay(1500);
console.log('Updating user profile:', userId, updateData);
return {
success: true,
message: 'Profile updated successfully'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Reset password
async resetPassword(email) {
try {
await this.delay(2000);
console.log('Password reset requested for:', email);
return {
success: true,
message: 'Password reset instructions sent to your email'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Logout
async logout() {
try {
await this.clearTokens();
await AsyncStorage.removeItem('userData');
await AsyncStorage.removeItem('user'); // New user key
await AsyncStorage.removeItem('@ndma_session_user');
console.log('✅ User logged out and storage cleared');
return {
success: true,
message: 'Logged out successfully'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Get current user from AsyncStorage
async getCurrentUser() {
try {
let userDataString = await AsyncStorage.getItem('userData');
if (!userDataString) {
userDataString = await AsyncStorage.getItem('user'); // Fallback for NewAuthService
}
if (userDataString) {
const userData = JSON.parse(userDataString);
console.log('✅ Retrieved current user:', userData.email || userData.phone);
return userData;
}
console.log('❌ No user data found in storage');
return null;
} catch (error) {
console.error('❌ Error getting current user:', error);
throw error;
}
}
// Update user profile
async updateProfile(updateData) {
try {
let userDataString = await AsyncStorage.getItem('userData');
let key = 'userData';
if (!userDataString) {
userDataString = await AsyncStorage.getItem('user');
key = 'user';
}
if (userDataString) {
const userData = JSON.parse(userDataString);
const updatedUser = { ...userData, ...updateData };
await AsyncStorage.setItem(key, JSON.stringify(updatedUser));
console.log('✅ Profile updated successfully');
return updatedUser;
}
throw new Error('No user data found');
} catch (error) {
console.error('❌ Error updating profile:', error);
throw error;
}
}
// Upload profile picture (mock implementation)
async uploadProfilePicture(imageUri) {
try {
// In real implementation, this would upload to a server
console.log('📸 Uploading profile picture:', imageUri);
await this.delay(1500);
// Return the image URI as the "uploaded" URL
return imageUri;
} catch (error) {
console.error('❌ Error uploading profile picture:', error);
throw error;
}
}
// Delay helper for simulating async operations
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Helper methods
// Validate email format
validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// Validate password strength
validatePassword(password) {
if (password.length < 6) {
return { valid: false, message: 'Password must be at least 6 characters long' };
}
return { valid: true };
}
// Get test credentials
getTestCredentials() {
return {
email: 'test@example.com',
password: 'password123',
description: 'Test account for development'
};
}
}
// Export singleton instance
const authService = new AuthService();
// Export as both default and named export for compatibility
export default authService;
export { authService };