fix : auth middleware

This commit is contained in:
2025-05-14 11:44:46 +03:30
parent 9a8ab8467b
commit 60f7cd85be
30 changed files with 160 additions and 730 deletions

View File

@@ -1,37 +1,13 @@
/*
import 'package:get_it/get_it.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:logger/logger.dart';
import 'package:rasadyar_app/data/data_provider/local_storage/hive/hive_provider.dart';
import 'package:rasadyar_app/data/data_source/local_storage/user/user_local_storage.dart';
import 'package:rasadyar_app/data/model/user/user_model.dart';
import 'package:rasadyar_app/domain/repository/user/user_repository.dart';
import 'package:rasadyar_auth/auth.dart';
import 'package:rasadyar_core/core.dart';
final di = GetIt.instance;
void setupInjection() {
di.registerLazySingleton(() => HiveProvider(), instanceName: 'HiveProvider');
di.registerSingleton<Logger>( Logger());
Future<void> setupInjection() async{
await setupAuthDI();
await setupAllProvider();
}
Future<void> setupAllProvider() async {
await _setupLocalStorage();
await di.allReady();
}
Future<void> _setupLocalStorage() async {
final hiveProvider = di.get<HiveProvider>(instanceName: 'HiveProvider');
await hiveProvider.init();
Hive.registerAdapter(UserModelAdapter());
await Hive.openBox<UserModel>(HiveBoxNames.user.name);
//user
di.registerLazySingleton<IUserLocalStorage>(() => UserLocalStorage());
di.registerLazySingleton<IUserRepository>(
() => UserRepository(di.get<IUserLocalStorage>()),
);
//
}
*/

View File

@@ -2,8 +2,11 @@ import 'package:flutter/material.dart';
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
import 'package:rasadyar_core/core.dart';
void main() async {
import 'infrastructure/di/di.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await setupInjection();
runApp(MyApp());
// runApp(DevicePreview(builder: (context) => ForDevicePreview(),));
@@ -41,12 +44,9 @@ class MyApp extends StatelessWidget {
colorScheme: ColorScheme.fromSeed(seedColor: AppColor.blueNormal),
),
initialRoute: AppPages.initRoutes,
// initialBinding: BindingsBuilder.put(() => UserService()),
getPages: AppPages.pages,
locale: const Locale("fa", "IR"),
supportedLocales: const [
Locale("fa", "IR"),
],
supportedLocales: const [Locale("fa", "IR")],
localizationsDelegates: [
PersianMaterialLocalizations.delegate,
PersianCupertinoLocalizations.delegate,

View File

@@ -1,69 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
enum AuthType { useAndPass, otp }
enum AuthStatus { init }
enum OtpStatus { init, sent, verified, reSend }
class AuthWithUseAndPassLogic extends GetxController {
Rx<GlobalKey<FormState>> formKey = GlobalKey<FormState>().obs;
Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
Rx<TextEditingController> phoneNumberController = TextEditingController().obs;
Rx<TextEditingController> passwordController = TextEditingController().obs;
Rx<TextEditingController> phoneOtpNumberController =
TextEditingController().obs;
Rx<TextEditingController> otpCodeController = TextEditingController().obs;
CaptchaController captchaController = CaptchaController();
CaptchaController captchaOtpController = CaptchaController();
RxnString phoneNumber = RxnString(null);
RxnString password = RxnString(null);
RxBool isOnError = false.obs;
RxBool hidePassword = true.obs;
Rx<AuthType> authType = AuthType.useAndPass.obs;
Rx<AuthStatus> authStatus = AuthStatus.init.obs;
Rx<OtpStatus> otpStatus = OtpStatus.init.obs;
RxInt secondsRemaining = 120.obs;
Timer? _timer;
void startTimer() {
_timer?.cancel();
secondsRemaining.value = 120;
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (secondsRemaining.value > 0) {
secondsRemaining.value--;
} else {
timer.cancel();
}
});
}
void stopTimer() {
_timer?.cancel();
}
String get timeFormatted {
final minutes = secondsRemaining.value ~/ 60;
final seconds = secondsRemaining.value % 60;
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
@override
void onReady() {
// TODO: implement onReady
super.onReady();
}
@override
void onClose() {
_timer?.cancel();
super.onClose();
}
}

View File

@@ -1,522 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
const AuthWithUseAndPassPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 80),
logoWidget(),
ObxValue((types) {
switch (types.value) {
case AuthType.otp:
return otpForm();
case AuthType.useAndPass:
return useAndPassFrom();
}
}, controller.authType),
SizedBox(height: 50),
RichText(
text: TextSpan(
children: [
TextSpan(
text: 'مطالعه بیانیه ',
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDark,
),
),
TextSpan(
recognizer: TapGestureRecognizer()..onTap = () {},
text: 'حریم خصوصی',
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
),
],
),
),
SizedBox(height: 18),
ObxValue((types) {
return RichText(
text: TextSpan(
children: [
TextSpan(
recognizer:
TapGestureRecognizer()
..onTap = () {
if (controller.authType.value == AuthType.otp) {
controller.authType.value = AuthType.useAndPass;
if (controller.otpStatus.value !=
OtpStatus.init) {
controller.otpStatus.value = OtpStatus.init;
}
} else {
controller.authType.value = AuthType.otp;
}
},
text:
controller.authType.value == AuthType.otp
? 'ورود با رمز ثابت'
: 'ورود با رمز یکبار مصرف',
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
),
],
),
);
}, controller.authType),
],
),
),
);
}
Widget useAndPassFrom() {
return ObxValue((data) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
child: Form(
key: data.value,
child: Column(
children: [
ObxValue((phoneController) {
return TextFormField(
controller: controller.phoneNumberController.value,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
gapPadding: 11,
),
labelText: 'شماره موبایل',
labelStyle: AppFonts.yekan13,
errorStyle: AppFonts.yekan13.copyWith(
color: AppColor.redNormal,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 40,
minHeight: 40,
maxWidth: 40,
minWidth: 40,
),
prefixIcon: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
child: vecWidget(Assets.vecCallSvg),
),
suffix:
phoneController.value.text.trim().isNotEmpty
? clearButton(() {
phoneController.value.clear();
phoneController.refresh();
})
: null,
counterText: '',
),
keyboardType: TextInputType.numberWithOptions(
decimal: false,
signed: false,
),
maxLines: 1,
maxLength: 11,
onChanged: (value) {
if (controller.isOnError.value) {
controller.isOnError.value = !controller.isOnError.value;
data.value.currentState?.reset();
data.refresh();
phoneController.value.text = value;
}
phoneController.refresh();
},
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null) {
return '⚠️ شماره موبایل را وارد کنید';
} else if (value.length < 11) {
return '⚠️ شماره موبایل باید 11 رقم باشد';
}
return null;
},
style: AppFonts.yekan13,
);
}, controller.phoneNumberController),
SizedBox(height: 26),
ObxValue((passwordController) {
return TextFormField(
controller: passwordController.value,
obscureText: controller.hidePassword.value,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
gapPadding: 11,
),
labelText: 'رمز عبور',
labelStyle: AppFonts.yekan13,
errorStyle: AppFonts.yekan13.copyWith(
color: AppColor.redNormal,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 34,
minHeight: 34,
maxWidth: 34,
minWidth: 34,
),
prefixIcon: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: vecWidget(Assets.vecKeySvg),
),
suffix:
passwordController.value.text.trim().isNotEmpty
? GestureDetector(
onTap: () {
controller.hidePassword.value =
!controller.hidePassword.value;
},
child: Icon(
controller.hidePassword.value
? CupertinoIcons.eye
: CupertinoIcons.eye_slash,
),
)
: null,
counterText: '',
),
textInputAction: TextInputAction.done,
keyboardType: TextInputType.visiblePassword,
maxLines: 1,
onChanged: (value) {
if (controller.isOnError.value) {
controller.isOnError.value = !controller.isOnError.value;
data.value.currentState?.reset();
passwordController.value.text = value;
}
passwordController.refresh();
},
validator: (value) {
if (value == null || value.isEmpty) {
return '⚠️ رمز عبور را وارد کنید'; // "Please enter the password"
}
return null;
},
style: AppFonts.yekan13,
);
}, controller.passwordController),
SizedBox(height: 26),
CaptchaWidget(controller: controller.captchaController),
SizedBox(height: 23),
RElevated(
text: 'ورود',
onPressed: () async {
Jalali? picked = await showPersianDatePicker(
context: Get.context!,
initialDate: Jalali.now(),
firstDate: Jalali(1385, 8),
lastDate: Jalali(1450, 9),
initialEntryMode: PersianDatePickerEntryMode.calendarOnly,
initialDatePickerMode: PersianDatePickerMode.year,
);
if (data.value.currentState?.validate() == true &&
controller.captchaController.validate()) {}
},
width: Get.width,
height: 48,
),
],
),
),
);
}, controller.formKey);
}
Widget otpForm() {
return ObxValue((status) {
switch (status.value) {
case OtpStatus.init:
return sendCodeForm();
case OtpStatus.sent:
case OtpStatus.verified:
case OtpStatus.reSend:
return confirmCodeForm();
}
}, controller.otpStatus);
}
Widget sendCodeForm() {
return ObxValue((data) {
return Form(
key: data.value,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
child: Column(
children: [
SizedBox(height: 26),
ObxValue((phoneController) {
return TextFormField(
controller: phoneController.value,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
gapPadding: 11,
),
labelText: 'شماره موبایل',
labelStyle: AppFonts.yekan13,
errorStyle: AppFonts.yekan13.copyWith(
color: AppColor.redNormal,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 40,
minHeight: 40,
maxWidth: 40,
minWidth: 40,
),
prefixIcon: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
child: vecWidget(Assets.vecCallSvg),
),
suffix:
phoneController.value.text.trim().isNotEmpty
? clearButton(() {
phoneController.value.clear();
phoneController.refresh();
})
: null,
counterText: '',
),
keyboardType: TextInputType.numberWithOptions(
decimal: false,
signed: false,
),
maxLines: 1,
maxLength: 11,
onChanged: (value) {
if (controller.isOnError.value) {
controller.isOnError.value = !controller.isOnError.value;
data.value.currentState?.reset();
data.refresh();
phoneController.value.text = value;
}
phoneController.refresh();
},
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null) {
return '⚠️ شماره موبایل را وارد کنید';
} else if (value.length < 11) {
return '⚠️ شماره موبایل باید 11 رقم باشد';
}
return null;
},
style: AppFonts.yekan13,
);
}, controller.phoneOtpNumberController),
SizedBox(height: 26),
CaptchaWidget(controller: controller.captchaOtpController),
SizedBox(height: 23),
RElevated(
text: 'ارسال رمز یکبار مصرف',
onPressed: () {
if (data.value.currentState?.validate() == true &&
controller.captchaOtpController.validate()) {
controller.otpStatus.value = OtpStatus.sent;
controller.startTimer();
}
},
width: Get.width,
height: 48,
),
],
),
),
);
}, controller.formKeyOtp);
}
Widget confirmCodeForm() {
return ObxValue((data) {
return Form(
key: data.value,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
child: Column(
children: [
SizedBox(height: 26),
ObxValue((passwordController) {
return TextFormField(
controller: passwordController.value,
obscureText: controller.hidePassword.value,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
gapPadding: 11,
),
labelText: 'رمز عبور',
labelStyle: AppFonts.yekan13,
errorStyle: AppFonts.yekan13.copyWith(
color: AppColor.redNormal,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 34,
minHeight: 34,
maxWidth: 34,
minWidth: 34,
),
prefixIcon: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: vecWidget(Assets.vecKeySvg),
),
suffix:
passwordController.value.text.trim().isNotEmpty
? GestureDetector(
onTap: () {
controller.hidePassword.value =
!controller.hidePassword.value;
},
child: Icon(
controller.hidePassword.value
? CupertinoIcons.eye
: CupertinoIcons.eye_slash,
),
)
: null,
counterText: '',
),
textInputAction: TextInputAction.done,
keyboardType: TextInputType.visiblePassword,
maxLines: 1,
onChanged: (value) {
if (controller.isOnError.value) {
controller.isOnError.value = !controller.isOnError.value;
data.value.currentState?.reset();
passwordController.value.text = value;
}
passwordController.refresh();
},
validator: (value) {
if (value == null || value.isEmpty) {
return '⚠️ رمز عبور را وارد کنید'; // "Please enter the password"
}
return null;
},
style: AppFonts.yekan13,
);
}, controller.passwordController),
SizedBox(height: 23),
ObxValue((timer) {
if (timer.value == 0) {
return TextButton(
onPressed: () {
controller.otpStatus.value = OtpStatus.reSend;
controller.startTimer();
},
child: Text(
style: AppFonts.yekan13.copyWith(
color: AppColor.blueNormal,
),
'ارسال مجدد کد یکبار مصرف',
),
);
} else {
return Text(
'اعتبار رمز ارسال شده ${controller.timeFormatted}',
style: AppFonts.yekan13,
);
}
}, controller.secondsRemaining),
RichText(
text: TextSpan(
children: [
TextSpan(
text: ' کد ارسال شده به شماره ',
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDark,
),
),
TextSpan(
text: controller.phoneOtpNumberController.value.text,
style: AppFonts.yekan13Bold.copyWith(
color: AppColor.darkGreyDark,
),
),
TextSpan(
recognizer:
TapGestureRecognizer()
..onTap = () {
controller.otpStatus.value = OtpStatus.init;
controller.captchaOtpController.clear();
},
text: ' ویرایش',
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
),
],
),
),
SizedBox(height: 23),
RElevated(
text: 'ورود',
onPressed: () {
if (controller.formKeyOtp.value.currentState?.validate() ==
true &&
controller.captchaOtpController.validate()) {}
},
width: Get.width,
height: 48,
),
],
),
),
);
}, controller.formKeySentOtp);
}
Widget logoWidget() {
return Column(
children: [
Row(),
Image.asset(Assets.imagesInnerSplash, width: 120, height: 120),
Text(
'سامانه رصدیار',
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyNormal),
),
],
);
}
Widget clearButton(VoidCallback onTap) {
return GestureDetector(
onTap: onTap,
child: Icon(CupertinoIcons.multiply_circle, size: 24),
);
}
}

View File

@@ -1,7 +1,6 @@
import 'package:flutter/animation.dart';
import 'package:get/get.dart';
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
import '';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/inspection.dart';
class SplashLogic extends GetxController with GetTickerProviderStateMixin {
late final AnimationController scaleController;

View File

@@ -1,10 +1,9 @@
import 'package:get/get.dart';
import 'package:rasadyar_app/presentation/pages/auth/auth_with_use_and_pass/logic.dart';
import 'package:rasadyar_app/presentation/pages/auth/auth_with_use_and_pass/view.dart';
import 'package:rasadyar_app/presentation/pages/splash/logic.dart';
import 'package:rasadyar_app/presentation/pages/splash/view.dart';
import 'package:rasadyar_app/presentation/pages/system_design/system_design.dart';
import 'package:rasadyar_auth/presentation/routes/pages.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/inspection.dart';
part 'app_paths.dart';
@@ -21,12 +20,9 @@ sealed class AppPages {
page: () => SplashPage(),
binding: BindingsBuilder.put(() => SplashLogic()),
),
GetPage(
name: AppPaths.authWithUserAndPass,
page: () => AuthWithUseAndPassPage(),
binding: BindingsBuilder.put(() => AuthWithUseAndPassLogic()),
),
...InspectionPages.pages,
...AuthPages.pages,
];
}

View File

@@ -4,7 +4,5 @@ sealed class AppPaths {
AppPaths._();
static const String splash = '/splash';
static const String authWithUserAndPass = '/authWithUserAndPass';
static const String authWithOtp = '/authWithOtp';
static const String systemDesignPage = '/systemDesignPage';
}