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

Change credentials storage to FlutterSecureStorage and remove WillPopScope #935

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
33 changes: 17 additions & 16 deletions uni/lib/controller/local_storage/app_shared_preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';

import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tuple/tuple.dart';
import 'package:uni/model/entities/exam.dart';
Expand Down Expand Up @@ -61,13 +62,12 @@ class AppSharedPreferences {
String pass,
List<String> faculties,
) async {
const storage = FlutterSecureStorage();
final prefs = await SharedPreferences.getInstance();
await prefs.setString(userNumber, user);
await prefs.setString(userPw, encode(pass));
await prefs.setStringList(
userFaculties,
faculties,
); // Could be multiple faculties

await prefs.setStringList(userFaculties, faculties);
await storage.write(key: userNumber, value: user);
await storage.write(key: userPw, value: encode(pass));
}

/// Sets whether or not the Terms and Conditions have been accepted.
Expand Down Expand Up @@ -119,9 +119,9 @@ class AppSharedPreferences {

/// Deletes the user's student number and password.
static Future<void> removePersistentUserInfo() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(userNumber);
await prefs.remove(userPw);
const storage = FlutterSecureStorage();
await storage.delete(key: userNumber);
await storage.delete(key: userPw);
}

/// Returns a tuple containing the user's student number and password.
Expand All @@ -146,21 +146,22 @@ class AppSharedPreferences {

/// Returns the user's student number.
static Future<String> getUserNumber() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(userNumber) ??
const storage = FlutterSecureStorage();
final usernumber = await storage.read(key: userNumber) ??
''; // empty string for the case it does not exist
return usernumber;
}

/// Returns the user's password, in plain text format.
static Future<String> getUserPassword() async {
final prefs = await SharedPreferences.getInstance();
var pass = prefs.getString(userPw) ?? '';
const storage = FlutterSecureStorage();
var userpass = await storage.read(key: userPw) ?? '';

if (pass != '') {
pass = decode(pass);
if (userpass != '') {
userpass = decode(userpass);
}

return pass;
return userpass;
}

/// Replaces the user's favorite widgets with [newFavorites].
Expand Down
29 changes: 1 addition & 28 deletions uni/lib/view/home/widgets/exit_app_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// Manages the app section displayed when the user presses the back button
class BackButtonExitWrapper extends StatelessWidget {
Expand All @@ -12,34 +11,8 @@ class BackButtonExitWrapper extends StatelessWidget {
final BuildContext context;
final Widget child;

Future<void> backButton() {
return showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: Text(
'Tens a certeza de que pretendes sair?',
style: Theme.of(context).textTheme.headlineSmall,
),
actions: <Widget>[
ElevatedButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text('Não'),
),
ElevatedButton(
onPressed: () =>
SystemChannels.platform.invokeMethod('SystemNavigator.pop'),
child: const Text('Sim'),
)
],
),
);
}

@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => backButton() as Future<bool>,
child: child,
);
return child;
}
}
99 changes: 39 additions & 60 deletions uni/lib/view/login/login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ class LoginPageViewState extends State<LoginPageView> {
TextEditingController();

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
static bool _exitApp = false;
bool _keepSignedIn = true;
bool _obscurePasswordInput = true;

Future<void> _login(BuildContext context) async {
final stateProviders = StateProviders.fromContext(context);
final sessionProvider = stateProviders.sessionProvider;

if (sessionProvider.status != RequestStatus.busy &&
_formKey.currentState!.validate()) {
final user = usernameController.text.trim();
Expand Down Expand Up @@ -109,78 +109,57 @@ class LoginPageViewState extends State<LoginPageView> {
child: Builder(
builder: (context) => Scaffold(
backgroundColor: darkRed,
body: WillPopScope(
child: Padding(
padding: EdgeInsets.only(
left: queryData.size.width / 8,
right: queryData.size.width / 8,
),
child: ListView(
children: [
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 20,
),
body: Padding(
padding: EdgeInsets.only(
left: queryData.size.width / 8,
right: queryData.size.width / 8,
),
child: ListView(
children: [
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 20,
),
createTitle(queryData, context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
),
createTitle(queryData, context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
getLoginForm(queryData, context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
),
getLoginForm(queryData, context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
createForgetPasswordLink(context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 15,
),
),
createForgetPasswordLink(context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 15,
),
createLogInButton(queryData, context, _login),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
),
createLogInButton(queryData, context, _login),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
createStatusWidget(context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
),
createStatusWidget(context),
Padding(
padding: EdgeInsets.only(
bottom: queryData.size.height / 35,
),
createSafeLoginButton(context),
],
),
),
createSafeLoginButton(context),
],
),
onWillPop: () => onWillPop(context),
Sanat2002 marked this conversation as resolved.
Show resolved Hide resolved
),
),
),
);
}

/// Delay time before the user leaves the app
Future<void> exitAppWaiter() async {
_exitApp = true;
await Future<void>.delayed(const Duration(seconds: 2));
_exitApp = false;
}

/// If the user tries to leave, displays a quick prompt for him to confirm.
/// If this is already the second time, the user leaves the app.
Future<bool> onWillPop(BuildContext context) {
if (_exitApp) {
return Future.value(true);
}
ToastMessage.info(context, 'Pressione novamente para sair');
exitAppWaiter();
return Future.value(false);
}

/// Creates the title for the login menu.
Widget createTitle(MediaQueryData queryData, BuildContext context) {
return ConstrainedBox(
Expand Down
4 changes: 4 additions & 0 deletions uni/linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@

#include "generated_plugin_registrant.h"

#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <sentry_flutter/sentry_flutter_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
Expand Down
1 change: 1 addition & 0 deletions uni/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#

list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
sentry_flutter
url_launcher_linux
)
Expand Down
1 change: 1 addition & 0 deletions uni/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies:
flutter_map: ^4.0.0
flutter_map_marker_popup: ^5.0.0
flutter_markdown: ^0.6.0
flutter_secure_storage: ^8.0.0
flutter_svg: ^2.0.0+1
flutter_widget_from_html_core: ^0.10.3
html: ^0.15.0
Expand Down
1 change: 1 addition & 0 deletions uni/windows/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus
flutter_secure_storage_windows
sentry_flutter
url_launcher_windows
)
Expand Down