Add automatic background lock to home screen; refactor repo names

This commit is contained in:
mitchell 2019-07-11 02:32:17 -04:00
parent 27215e6596
commit 474f0c056b
10 changed files with 74 additions and 44 deletions

View File

@ -4,12 +4,12 @@ PODS:
- Flutter - Flutter
DEPENDENCIES: DEPENDENCIES:
- Flutter (from `.symlinks/flutter/ios-release`) - Flutter (from `.symlinks/flutter/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
EXTERNAL SOURCES: EXTERNAL SOURCES:
Flutter: Flutter:
:path: ".symlinks/flutter/ios-release" :path: ".symlinks/flutter/ios"
flutter_secure_storage: flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios" :path: ".symlinks/plugins/flutter_secure_storage/ios"

View File

@ -253,7 +253,7 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (

View File

@ -1,8 +1,8 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'repositories/credentials_client.dart'; import 'repositories/grpc_credentials_client.dart';
import 'repositories/config.dart' as repo; import 'repositories/secure_storage_config.dart';
import 'screens/authentication.dart'; import 'screens/authentication.dart';
import 'screens/credential.dart'; import 'screens/credential.dart';
@ -19,7 +19,7 @@ class Selfpass extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Provider<ConfigRepo>( return Provider<ConfigRepo>(
builder: (BuildContext context) => repo.Config(), builder: (BuildContext context) => SecureStorageConfig(),
child: CupertinoApp( child: CupertinoApp(
title: 'Selfpass', title: 'Selfpass',
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
@ -36,7 +36,7 @@ class Selfpass extends StatelessWidget {
title = 'Hosts'; title = 'Hosts';
builder = (BuildContext context) => Provider<CredentialsRepo>( builder = (BuildContext context) => Provider<CredentialsRepo>(
builder: (BuildContext context) => builder: (BuildContext context) =>
CredentialsClient.cached(config: settings.arguments), GRPCCredentialsClient.cached(config: settings.arguments),
child: Home(), child: Home(),
); );
break; break;
@ -45,7 +45,7 @@ class Selfpass extends StatelessWidget {
title = 'Credentials'; title = 'Credentials';
builder = (BuildContext context) => Provider<CredentialsRepo>( builder = (BuildContext context) => Provider<CredentialsRepo>(
builder: (BuildContext context) => builder: (BuildContext context) =>
CredentialsClient.cached(), GRPCCredentialsClient.cached(),
child: Credentials(settings.arguments), child: Credentials(settings.arguments),
); );
break; break;
@ -54,7 +54,7 @@ class Selfpass extends StatelessWidget {
title = 'Credential'; title = 'Credential';
builder = (BuildContext context) => Provider<CredentialsRepo>( builder = (BuildContext context) => Provider<CredentialsRepo>(
builder: (BuildContext context) => builder: (BuildContext context) =>
CredentialsClient.cached(), GRPCCredentialsClient.cached(),
child: Credential(settings.arguments), child: Credential(settings.arguments),
); );
break; break;
@ -63,6 +63,7 @@ class Selfpass extends StatelessWidget {
final ConfigScreenArguments arguments = settings.arguments == null final ConfigScreenArguments arguments = settings.arguments == null
? ConfigScreenArguments() ? ConfigScreenArguments()
: settings.arguments; : settings.arguments;
title = 'Configuration'; title = 'Configuration';
builder = (BuildContext context) => builder = (BuildContext context) =>
Config(arguments.connectionConfig, arguments.privateKey); Config(arguments.connectionConfig, arguments.privateKey);

View File

@ -11,11 +11,11 @@ import '../types/abstracts.dart';
import '../types/connection_config.dart'; import '../types/connection_config.dart';
import '../types/credential.dart'; import '../types/credential.dart';
class CredentialsClient implements CredentialsRepo { class GRPCCredentialsClient implements CredentialsRepo {
static CredentialsClient _cached; static GRPCCredentialsClient _cached;
grpc.CredentialServiceClient _client; grpc.CredentialServiceClient _client;
CredentialsClient(ConnectionConfig config) { GRPCCredentialsClient(ConnectionConfig config) {
final caCert = utf8.encode(config.caCertificate); final caCert = utf8.encode(config.caCertificate);
final cert = utf8.encode(config.certificate); final cert = utf8.encode(config.certificate);
final privateCert = utf8.encode(config.privateCertificate); final privateCert = utf8.encode(config.privateCertificate);
@ -33,8 +33,8 @@ class CredentialsClient implements CredentialsRepo {
)); ));
} }
factory CredentialsClient.cached({ConnectionConfig config}) => factory GRPCCredentialsClient.cached({ConnectionConfig config}) =>
_cached == null ? _cached = CredentialsClient(config) : _cached; config == null ? _cached : _cached = GRPCCredentialsClient(config);
Stream<Metadata> getAllMetadata(String sourceHost) { Stream<Metadata> getAllMetadata(String sourceHost) {
final request = grpc.GetAllMetadataRequest(); final request = grpc.GetAllMetadataRequest();

View File

@ -7,11 +7,13 @@ import '../types/connection_config.dart';
import '../utils/crypto.dart' as crypto; import '../utils/crypto.dart' as crypto;
class Config implements ConfigRepo { class SecureStorageConfig implements ConfigRepo {
static const _keyPrivateKey = "private_key"; static const _keyPrivateKey = "private_key";
static const _keyConnectionConfig = "connection_config"; static const _keyConnectionConfig = "connection_config";
static const _keyPassword = "password"; static const _keyPassword = "password";
final FlutterSecureStorage _storage = FlutterSecureStorage();
final _storage = FlutterSecureStorage();
bool _passwordMatched = false; bool _passwordMatched = false;
String _password; String _password;
@ -32,13 +34,15 @@ class Config implements ConfigRepo {
Future<void> setPassword(String password) { Future<void> setPassword(String password) {
_checkIfPasswordMatched(); _checkIfPasswordMatched();
_password = password; _password = password;
return _storage.write( return _storage.write(
key: _keyPassword, value: crypto.hashPassword(password)); key: _keyPassword, value: crypto.hashPassword(password));
} }
Future<bool> get passwordSet async { Future<bool> get passwordIsSet async {
var passHash = await _storage.read(key: _keyPassword); final passHash = await _storage.read(key: _keyPassword);
if (passHash != null) { if (passHash != null) {
return true; return true;
@ -53,9 +57,7 @@ class Config implements ConfigRepo {
_passwordMatched = crypto.matchHashedPassword( _passwordMatched = crypto.matchHashedPassword(
await _storage.read(key: _keyPassword), password); await _storage.read(key: _keyPassword), password);
if (_passwordMatched) { if (_passwordMatched) _password = password;
_password = password;
}
return _passwordMatched; return _passwordMatched;
} }

View File

@ -22,7 +22,7 @@ class _AuthenticationState extends State<Authentication> {
didChangeDependencies() { didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
_config = Provider.of<ConfigRepo>(context); _config = Provider.of<ConfigRepo>(context);
_passwordIsSet = _config.passwordSet; _passwordIsSet = _config.passwordIsSet;
} }
@override @override

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -8,32 +10,56 @@ import '../types/screen_arguments.dart';
import '../widgets/tappable_text_list.dart'; import '../widgets/tappable_text_list.dart';
class Home extends StatefulWidget { class Home extends StatefulWidget {
const Home({Key key}) : super(key: key);
@override @override
State createState() => _HomeState(); State createState() => _HomeState();
} }
class _HomeState extends State<Home> { class _HomeState extends State<Home> with WidgetsBindingObserver {
CredentialsRepo _client; CredentialsRepo _client;
ConfigRepo _config; ConfigRepo _config;
Future<List<Metadata>> _metadatas; Future<List<Metadata>> _metadatas;
bool _stateIsPaused = false;
Timer _pausedStateTimer;
@override @override
didChangeDependencies() { void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
_config = Provider.of<ConfigRepo>(context); _config = Provider.of<ConfigRepo>(context);
_client = Provider.of<CredentialsRepo>(context); _client = Provider.of<CredentialsRepo>(context);
_metadatas = _client.getAllMetadata('').toList(); _metadatas = _client.getAllMetadata('').toList();
} }
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
_stateIsPaused = state == AppLifecycleState.paused;
if (_stateIsPaused) {
_pausedStateTimer = _newPausedStateTimer();
return;
}
if (_pausedStateTimer != null) _pausedStateTimer.cancel();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CupertinoPageScaffold( return CupertinoPageScaffold(
child: FutureBuilder<List<Metadata>>( child: FutureBuilder<List<Metadata>>(
future: _metadatas, future: _metadatas,
builder: (BuildContext context, builder: (
AsyncSnapshot<List<Metadata>> snapshot) => BuildContext context,
AsyncSnapshot<List<Metadata>> snapshot,
) =>
(snapshot.connectionState == ConnectionState.done) (snapshot.connectionState == ConnectionState.done)
? TappableTextList( ? TappableTextList(
tappableText: _buildTappableText(context, snapshot.data)) tappableText: _buildTappableText(context, snapshot.data))
@ -55,6 +81,22 @@ class _HomeState extends State<Home> {
); );
} }
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
if (_pausedStateTimer != null) _pausedStateTimer.cancel();
super.dispose();
}
Timer _newPausedStateTimer() {
const checkPeriod = 30;
return Timer(Duration(seconds: checkPeriod), () {
Navigator.of(context)
.pushNamedAndRemoveUntil('/', ModalRoute.withName('/home'));
});
}
Map<String, GestureTapCallback> _buildTappableText( Map<String, GestureTapCallback> _buildTappableText(
BuildContext context, BuildContext context,
List<Metadata> metadatas, List<Metadata> metadatas,

View File

@ -17,7 +17,7 @@ abstract class ConfigRepo {
String get password; String get password;
Future<void> setPassword(String password); Future<void> setPassword(String password);
Future<bool> get passwordSet; Future<bool> get passwordIsSet;
Future<bool> matchesPasswordHash(String password); Future<bool> matchesPasswordHash(String password);
Future<void> setConnectionConfig(ConnectionConfig config); Future<void> setConnectionConfig(ConnectionConfig config);

View File

@ -1,13 +1,6 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
_discoveryapis_commons:
dependency: transitive
description:
name: _discoveryapis_commons
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.8+1"
args: args:
dependency: transitive dependency: transitive
description: description:
@ -116,13 +109,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
googleapis:
dependency: "direct main"
description:
name: googleapis
url: "https://pub.dartlang.org"
source: hosted
version: "0.53.0"
googleapis_auth: googleapis_auth:
dependency: transitive dependency: transitive
description: description:

View File

@ -11,7 +11,7 @@ description: The cross-platform Selfpass client.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1 version: 0.1.0
environment: environment:
sdk: ">=2.1.0 <3.0.0" sdk: ">=2.1.0 <3.0.0"
@ -24,7 +24,6 @@ dependencies:
grpc: ^1.0.3 grpc: ^1.0.3
protobuf: ^0.13.12 protobuf: ^0.13.12
googleapis: ^0.53.0
provider: ^3.0.0 provider: ^3.0.0