Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remember me feature #2672

Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "Die Startzeit muss vor der Endzeit liegen",
"Organisation on different server, logout and scan qr again": "Organisation auf einem anderen Server, ausloggen und QR-Code erneut scannen",
"Post was deleted if you had the rights!": "Der Beitrag wurde gelöscht, wenn Sie die Berechtigungen hatten!",
"Members": "Mitglieder"
"Members": "Mitglieder",
"Remember me": "Erinnere dich an mich",
"Login directly with": "Direkt anmelden mit"
}
4 changes: 3 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "Start time must be before end time",
"Organisation on different server, logout and scan qr again": "Organisation on different server, logout and scan qr again",
"Post was deleted if you had the rights!": "Post was deleted if you had the rights!",
"Members": "Members"
"Members": "Members",
"Remember me": "Remember me",
"Login directly with": "Login directly with"
}
6 changes: 4 additions & 2 deletions lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "La hora de inicio debe ser anterior a la hora de finalización",
"Organisation on different server, logout and scan qr again": "Organización en un servidor diferente, cierre la sesión y escanee el código QR nuevamente",
"Post was deleted if you had the rights!": "¡Se eliminó la publicación si tenías los derechos!",
"Members": "Miembros"
}
"Members": "Miembros",
"Remember me": "Recuérdame",
"Login directly with": "Iniciar sesión directamente con"
}
6 changes: 4 additions & 2 deletions lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "L'heure de début doit être antérieure à l'heure de fin",
"Organisation on different server, logout and scan qr again": "Organisation sur un serveur différent, déconnectez-vous et scannez à nouveau le code QR",
"Post was deleted if you had the rights!": "Le message a été supprimé si vous aviez les droits !",
"Members": " Membres"
}
"Members": " Membres",
"Remember me": "Souviens-toi de moi",
"Login directly with": "Se connecter directement avec"
}
6 changes: 4 additions & 2 deletions lang/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "शुरू समय अंत समय से पहले होना चाहिए",
"Organisation on different server, logout and scan qr again": "संगठन अलग सर्वर पर है, लॉगआउट करें और फिर से QR स्कैन करें",
"Post was deleted if you had the rights!": "यदि आपके पास अधिकार थे तो पोस्ट हटा दिया गया था!",
"Members": " सदस्य"
}
"Members": " सदस्य",
"Remember me": "मुझे याद रखें",
"Login directly with": "इसके साथ सीधे लॉगिन करें"
}
6 changes: 4 additions & 2 deletions lang/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "開始時間は終了時間より前でなければなりません",
"Organisation on different server, logout and scan qr again": "異なるサーバー上の組織です。ログアウトして、QRコードを再びスキャンしてください。",
"Post was deleted if you had the rights!": "権限がある場合、投稿は削除されました!",
"Members": " メンバー "
}
"Members": " メンバー ",
"Remember me": "ログイン情報を保存",
"Login directly with": "直接ログイン"
}
4 changes: 3 additions & 1 deletion lang/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "O horário de início deve ser anterior ao horário de término",
"Organisation on different server, logout and scan qr again": "Organização em servidor diferente, faça logout e escaneie o QR novamente",
"Post was deleted if you had the rights!": "A postagem foi excluída se você tiver os direitos!",
"Members": "Membros"
"Members": "Membros",
"Remember me": "Lembre-se de mim",
"Login directly with": "Entrar diretamente com"
}
6 changes: 4 additions & 2 deletions lang/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,7 @@
"Start time must be before end time": "开始时间必须在结束时间之前",
"Organisation on different server, logout and scan qr again": "组织在不同的服务器上,请注销并重新扫描二维码",
"Post was deleted if you had the rights!": "如果您有权限,则已删除帖子!",
"Members": "成员"
}
"Members": "成员",
"Remember me": "记住我",
"Login directly with": "直接登录"
}
14 changes: 7 additions & 7 deletions lib/services/user_config.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:hive/hive.dart';
Expand Down Expand Up @@ -131,7 +130,8 @@ class UserConfig {
/// None
///
/// **returns**:
/// * `Future<bool>`: returns future of bool type.
/// None

Future<void> userLogOut() async {
await actionHandlerService.performAction(
actionType: ActionType.critical,
Expand Down Expand Up @@ -196,7 +196,7 @@ class UserConfig {
/// * `orgDetails`: details of the organization that user joined.
///
/// **returns**:
/// * `Future<void>`: returns future of void type.
/// None
Future<void> updateUserJoinedOrg(List<OrgInfo> orgDetails) async {
_currentUser!.updateJoinedOrg(orgDetails);
saveUserInHive();
Expand All @@ -208,7 +208,7 @@ class UserConfig {
/// * `orgDetails`: details of the organization that user joined.
///
/// **returns**:
/// * `Future<void>`: returns future of void type.
/// None
Future<void> updateUserCreatedOrg(List<OrgInfo> orgDetails) async {
_currentUser!.updateCreatedOrg(orgDetails);
saveUserInHive();
Expand All @@ -220,7 +220,7 @@ class UserConfig {
/// * `orgDetails`: details of the organization that user joined.
///
/// **returns**:
/// * `Future<void>`: returns future of void type.
/// None
Future<void> updateUserMemberRequestOrg(List<OrgInfo> orgDetails) async {
_currentUser!.updateMemberRequestOrg(orgDetails);
saveUserInHive();
Expand All @@ -232,7 +232,7 @@ class UserConfig {
/// * `orgDetails`: details of the organization that user joined.
///
/// **returns**:
/// * `Future<void>`: returns future of void type.
/// None
Future<void> updateUserAdminOrg(List<OrgInfo> orgDetails) async {
_currentUser!.updateAdminFor(orgDetails);
saveUserInHive();
Expand All @@ -245,7 +245,7 @@ class UserConfig {
/// * `refreshToken`: current user's refreshtoken.
///
/// **returns**:
/// * `Future<void>`: returns future of void type.
/// None
Future<void> updateAccessToken({
required String accessToken,
required String refreshToken,
Expand Down
43 changes: 41 additions & 2 deletions lib/view_model/pre_auth_view_models/login_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:talawa/constants/app_strings.dart';

import 'package:talawa/constants/routing_constants.dart';
import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
// import 'package:talawa/main.dart';

import 'package:talawa/models/mainscreen_navigation_args.dart';
import 'package:talawa/models/user/user_info.dart';
import 'package:talawa/utils/encryptor.dart';
Expand All @@ -21,6 +22,15 @@
/// GlobalKey to identify and manage the state of a form widget.
final formKey = GlobalKey<FormState>();

/// This field store previous user Email.
String? prevUserEmail;

/// This field store previous user Password.
String? prevUserPassword;

/// Secure local storage instance.
final secureStorage = const FlutterSecureStorage();

/// List of maps to store greetings..
late List<Map<String, dynamic>> greeting;

Expand Down Expand Up @@ -146,7 +156,7 @@
userConfig.updateUser(loggedInUser);
}
},
apiCallSuccessUpdateUI: () {
apiCallSuccessUpdateUI: () async {
// if user has not already joined any organization.
if (userConfig.currentUser.joinedOrganizations!.isEmpty) {
navigationService.removeAllAndPush(
Expand All @@ -163,6 +173,19 @@
arguments: MainScreenArgs(mainScreenIndex: 0, fromSignUp: false),
);
}
try {
await secureStorage.write(
key: "userEmail",
value: this.email.text,
);
await secureStorage.write(
key: "userPassword",
value: this.password.text,
);
} catch (e) {
// Handle secure storage write failure
print("Failed to save credentials: $e");

Check warning on line 187 in lib/view_model/pre_auth_view_models/login_view_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/view_model/pre_auth_view_models/login_view_model.dart#L187

Added line #L187 was not covered by tests
}
},
onActionException: (e) async {
print('here');
Expand All @@ -171,4 +194,20 @@
);
}
}

/// Fetch the previous user credentials.
///
/// **params**:
/// None
///
/// **returns**:
/// None
Future<void> fetchPrevUser() async {
try {
prevUserEmail = await secureStorage.read(key: "userEmail");
prevUserPassword = await secureStorage.read(key: "userPassword");

Check warning on line 208 in lib/view_model/pre_auth_view_models/login_view_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/view_model/pre_auth_view_models/login_view_model.dart#L208

Added line #L208 was not covered by tests
} catch (e) {
print("Error decrypting previous values $e");

Check warning on line 210 in lib/view_model/pre_auth_view_models/login_view_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/view_model/pre_auth_view_models/login_view_model.dart#L210

Added line #L210 was not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:talawa/constants/app_strings.dart';
import 'package:talawa/constants/routing_constants.dart';
Expand All @@ -25,6 +26,9 @@
/// Represents information about the selected organization.
late OrgInfo selectedOrganization;

/// Secure local storage instance.
final secureStorage = const FlutterSecureStorage();

/// TextEditingController for handling confirmation password input field.
TextEditingController confirmPassword = TextEditingController();

Expand Down Expand Up @@ -198,6 +202,19 @@
Routes.splashScreen,
);
}
try {
await secureStorage.write(
key: "userEmail",
value: this.email.text,
);
await secureStorage.write(
key: "userPassword",
value: this.password.text,
);
} catch (e) {
// Handle secure storage write failure
print("Failed to save credentials: $e");

Check warning on line 216 in lib/view_model/pre_auth_view_models/signup_details_view_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/view_model/pre_auth_view_models/signup_details_view_model.dart#L216

Added line #L216 was not covered by tests
}
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:talawa/constants/routing_constants.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/services/size_config.dart';
import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/view_model/after_auth_view_models/settings_view_models/app_setting_view_model.dart';
import 'package:talawa/views/base_view.dart';
import 'package:talawa/widgets/custom_alert_dialog.dart';
import 'package:talawa/widgets/custom_alert_dialog_with_checkbox.dart';
import 'package:talawa/widgets/lang_switch.dart';
import 'package:talawa/widgets/theme_switch.dart';

/// Widget representing the App Settings page.
///
/// This widget represents the settings page of the application.
/// It allows users to configure various application settings.
class AppSettingsPage extends StatelessWidget {
class AppSettingsPage extends StatefulWidget {
const AppSettingsPage({
super.key,
});

@override
State<AppSettingsPage> createState() => _AppSettingsPageState();
}

class _AppSettingsPageState extends State<AppSettingsPage> {
/// Secure local storage instance.
final secureStorage = const FlutterSecureStorage();

@override
Widget build(BuildContext context) {
const String talawaDocs = 'https://docs.talawa.io';
Expand Down Expand Up @@ -286,13 +295,27 @@
? showDialog(
context: context,
builder: (context) {
return CustomAlertDialog(
reverse: true,
dialogSubTitle: 'Are you sure you want to logout?',
successText: 'Logout',
success: () async {
return CustomAlertDialogWithCheckbox(
success: (checkBoxVal) async {
await model.logout();
if (checkBoxVal != null && checkBoxVal == false) {
try {
await secureStorage.delete(

Check warning on line 303 in lib/views/after_auth_screens/app_settings/app_settings_page.dart

View check run for this annotation

Codecov / codecov/patch

lib/views/after_auth_screens/app_settings/app_settings_page.dart#L303

Added line #L303 was not covered by tests
key: "userEmail",
);
await secureStorage.delete(

Check warning on line 306 in lib/views/after_auth_screens/app_settings/app_settings_page.dart

View check run for this annotation

Codecov / codecov/patch

lib/views/after_auth_screens/app_settings/app_settings_page.dart#L306

Added line #L306 was not covered by tests
key: "userPassword",
);
} catch (e) {
print("Unable to delete stored value : $e");

Check warning on line 310 in lib/views/after_auth_screens/app_settings/app_settings_page.dart

View check run for this annotation

Codecov / codecov/patch

lib/views/after_auth_screens/app_settings/app_settings_page.dart#L310

Added line #L310 was not covered by tests
}
}
},
reverse: true,
dialogSubTitle: "Are you sure you want to logout?",
checkboxLabel: "Remember me",
successText: "Logout",
initialCheckboxValue: true,
);
},
)
Expand Down
9 changes: 7 additions & 2 deletions lib/views/pre_auth_screens/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/utils/validators.dart';
import 'package:talawa/view_model/pre_auth_view_models/login_view_model.dart';
import 'package:talawa/views/base_view.dart';
import 'package:talawa/widgets/directly_login.dart';
import 'package:talawa/widgets/raised_round_edge_button.dart';
import 'package:talawa/widgets/rich_text.dart';

Expand All @@ -15,7 +16,8 @@ import 'package:talawa/widgets/rich_text.dart';
/// the second one takes in the password of the user.
/// There is also a "Forgot Password" text button, which directs to
/// the "recover password" screen when pressed.
/// At the bottom, there is a login button to initiate the login.
/// There is a login button to initiate the login.
/// At the bottom there is option to login directly with previous email.(This option is only available if user select remember me while logging out)
class Login extends StatefulWidget {
const Login({required Key key}) : super(key: key);

Expand All @@ -27,7 +29,9 @@ class _LoginState extends State<Login> {
@override
Widget build(BuildContext context) {
return BaseView<LoginViewModel>(
onModelReady: (model) => model.initialize(),
onModelReady: (model) {
model.initialize();
},
builder: (context, model, child) {
return Scaffold(
resizeToAvoidBottomInset: true,
Expand Down Expand Up @@ -186,6 +190,7 @@ class _LoginState extends State<Login> {
backgroundColor: Theme.of(context).colorScheme.tertiary,
),
SizedBox(height: SizeConfig.screenHeight! * 0.0215),
DirectlyLogin(model: model),
],
),
),
Expand Down
Loading
Loading