Initial commit: Uruk Prize Platform architecture, backend core, mobile app, gateway caller & deployment pipeline
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../core/network/api_client.dart';
|
||||
import '../../../core/security/fingerprint_service.dart';
|
||||
import 'auth_state.dart';
|
||||
|
||||
class AuthCubit extends Cubit<AuthState> {
|
||||
final ApiClient _apiClient;
|
||||
final FingerprintService _fingerprintService;
|
||||
|
||||
AuthCubit({
|
||||
ApiClient? apiClient,
|
||||
FingerprintService? fingerprintService,
|
||||
}) : _apiClient = apiClient ?? ApiClient(),
|
||||
_fingerprintService = fingerprintService ?? FingerprintService(),
|
||||
super(AuthInitial());
|
||||
|
||||
Future<void> checkExistingSession() async {
|
||||
try {
|
||||
final token = await _fingerprintService.getSessionToken();
|
||||
final userId = await _fingerprintService.getUserId();
|
||||
final fingerprint = await _fingerprintService.getDeviceFingerprint();
|
||||
|
||||
if (token != null && userId != null) {
|
||||
emit(Authenticated(
|
||||
user: {'id': userId, 'full_name': 'عضو أوروك'},
|
||||
token: token,
|
||||
deviceFingerprint: fingerprint,
|
||||
));
|
||||
} else {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
} catch (_) {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestOtp(String phone) async {
|
||||
emit(AuthLoading());
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'/api/v1/auth/request-otp',
|
||||
body: {'phone': phone},
|
||||
requiresAuth: false,
|
||||
);
|
||||
|
||||
final data = response['data'] as Map<String, dynamic>?;
|
||||
emit(AuthOtpSent(
|
||||
phone: phone,
|
||||
mockOtp: data?['mock_otp'] as String?,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(AuthFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyOtpAndBindDevice({
|
||||
required String phone,
|
||||
required String otp,
|
||||
String? fullName,
|
||||
}) async {
|
||||
emit(AuthLoading());
|
||||
try {
|
||||
final fingerprint = await _fingerprintService.getDeviceFingerprint();
|
||||
final model = await _fingerprintService.getDeviceModel();
|
||||
|
||||
final response = await _apiClient.post(
|
||||
'/api/v1/auth/verify-otp',
|
||||
body: {
|
||||
'phone': phone,
|
||||
'otp': otp,
|
||||
'device_fingerprint': fingerprint,
|
||||
'device_model': model,
|
||||
if (fullName != null && fullName.isNotEmpty) 'full_name': fullName,
|
||||
},
|
||||
requiresAuth: false,
|
||||
);
|
||||
|
||||
final data = response['data'] as Map<String, dynamic>;
|
||||
final user = data['user'] as Map<String, dynamic>;
|
||||
final token = data['token'] as String;
|
||||
final secret = data['device_secret'] as String;
|
||||
final userId = user['id'] as int;
|
||||
|
||||
await _fingerprintService.saveAuthSession(
|
||||
userId: userId,
|
||||
token: token,
|
||||
deviceSecret: secret,
|
||||
);
|
||||
|
||||
emit(Authenticated(
|
||||
user: user,
|
||||
token: token,
|
||||
deviceFingerprint: fingerprint,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(AuthFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _fingerprintService.clearSession();
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class AuthState extends Equatable {
|
||||
const AuthState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class AuthInitial extends AuthState {}
|
||||
|
||||
class AuthLoading extends AuthState {}
|
||||
|
||||
class AuthOtpSent extends AuthState {
|
||||
final String phone;
|
||||
final String? mockOtp;
|
||||
|
||||
const AuthOtpSent({required this.phone, this.mockOtp});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [phone, mockOtp];
|
||||
}
|
||||
|
||||
class Authenticated extends AuthState {
|
||||
final Map<String, dynamic> user;
|
||||
final String token;
|
||||
final String deviceFingerprint;
|
||||
|
||||
const Authenticated({
|
||||
required this.user,
|
||||
required this.token,
|
||||
required this.deviceFingerprint,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [user, token, deviceFingerprint];
|
||||
}
|
||||
|
||||
class Unauthenticated extends AuthState {}
|
||||
|
||||
class AuthFailure extends AuthState {
|
||||
final String errorMessage;
|
||||
|
||||
const AuthFailure(this.errorMessage);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [errorMessage];
|
||||
}
|
||||
Reference in New Issue
Block a user