mirror of
https://github.com/mitchell/selfpass.git
synced 2025-12-15 13:47:21 +00:00
Add decryption of credential encrypted fields; refactored config;
add app icon
This commit is contained in:
parent
910bdeae12
commit
27215e6596
60 changed files with 370 additions and 151 deletions
|
|
@ -105,10 +105,8 @@ class _AuthenticationState extends State<Authentication> {
|
|||
return () async {
|
||||
if (await _passwordIsSet) {
|
||||
if (await _config.matchesPasswordHash(_passwordController.text)) {
|
||||
Navigator.of(context).pushReplacementNamed(
|
||||
'/home',
|
||||
arguments: await _config.connectionConfig,
|
||||
);
|
||||
Navigator.of(context).pushReplacementNamed('/home',
|
||||
arguments: await _config.connectionConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:otp/otp.dart';
|
||||
|
||||
import '../types/credential.dart' as types;
|
||||
|
||||
|
|
@ -19,17 +20,14 @@ class _CredentialState extends State<Credential> {
|
|||
Map<String, _FieldBuildConfig> _fieldMap;
|
||||
types.Credential _credential;
|
||||
|
||||
_CredentialState(this._credential) : super() {
|
||||
_controllers = _CredentialControllers.fromCredential(_credential);
|
||||
_fieldMap = _buildFieldMap(_controllers, _credential);
|
||||
}
|
||||
_CredentialState(this._credential) : super();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(top: 30, left: 30),
|
||||
padding: const EdgeInsets.only(top: 15, bottom: 30, left: 30),
|
||||
child: ListView(
|
||||
children: _buildFieldRows(context),
|
||||
),
|
||||
|
|
@ -43,12 +41,12 @@ class _CredentialState extends State<Credential> {
|
|||
) {
|
||||
final fieldMap = {
|
||||
'Id:': _FieldBuildConfig(mutable: false, text: credential.meta.id),
|
||||
'Created: ': _FieldBuildConfig(
|
||||
'Created:': _FieldBuildConfig(
|
||||
mutable: false,
|
||||
copyable: false,
|
||||
text: credential.meta.createdAt.toString(),
|
||||
),
|
||||
'Updated: ': _FieldBuildConfig(
|
||||
'Updated:': _FieldBuildConfig(
|
||||
mutable: false,
|
||||
copyable: false,
|
||||
text: credential.meta.updatedAt.toString(),
|
||||
|
|
@ -69,15 +67,26 @@ class _CredentialState extends State<Credential> {
|
|||
fieldMap['Email:'] = _FieldBuildConfig(controller: controllers.email);
|
||||
}
|
||||
|
||||
fieldMap['Password:'] =
|
||||
_FieldBuildConfig(controller: controllers.password, obscured: true);
|
||||
|
||||
if (credential.otpSecret != null && credential.otpSecret != '') {
|
||||
fieldMap['OTP Secret:'] = _FieldBuildConfig(
|
||||
controller: controllers.otpSecret, obscured: true, otp: true);
|
||||
}
|
||||
|
||||
return fieldMap;
|
||||
}
|
||||
|
||||
List<Widget> _buildFieldRows(BuildContext context) {
|
||||
List<Widget> rows = [];
|
||||
|
||||
_controllers = _CredentialControllers.fromCredential(_credential);
|
||||
_fieldMap = _buildFieldMap(_controllers, _credential);
|
||||
|
||||
_fieldMap.forEach((key, value) {
|
||||
rows.add(Container(
|
||||
margin: EdgeInsets.only(top: 10),
|
||||
margin: EdgeInsets.only(top: 2.5),
|
||||
child: Text(key, style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
));
|
||||
|
||||
|
|
@ -85,20 +94,27 @@ class _CredentialState extends State<Credential> {
|
|||
Expanded(
|
||||
flex: 3,
|
||||
child: value.mutable
|
||||
? TextField(maxLines: 1, controller: value.controller)
|
||||
? TextField(
|
||||
maxLines: 1,
|
||||
controller: value.controller,
|
||||
obscure: value.obscured)
|
||||
: Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(value.text),
|
||||
),
|
||||
child: Text(value.text)),
|
||||
),
|
||||
];
|
||||
|
||||
if (value.copyable) {
|
||||
widgets.add(Flexible(
|
||||
widgets.add(Expanded(
|
||||
child: CupertinoButton(
|
||||
child: Text('Copy'),
|
||||
child: Text(value.otp ? 'OTP' : 'Copy'),
|
||||
onPressed: () => Clipboard.setData(ClipboardData(
|
||||
text: value.mutable ? value.controller.text : value.text,
|
||||
text: value.otp
|
||||
? OTP
|
||||
.generateTOTPCode(value.controller.text,
|
||||
DateTime.now().millisecondsSinceEpoch)
|
||||
.toString()
|
||||
: value.mutable ? value.controller.text : value.text,
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
|
@ -116,10 +132,14 @@ class _FieldBuildConfig {
|
|||
final String text;
|
||||
final bool mutable;
|
||||
final bool copyable;
|
||||
final bool obscured;
|
||||
final bool otp;
|
||||
|
||||
const _FieldBuildConfig({
|
||||
this.mutable = true,
|
||||
this.copyable = true,
|
||||
this.obscured = false,
|
||||
this.otp = false,
|
||||
this.controller,
|
||||
this.text,
|
||||
});
|
||||
|
|
@ -151,5 +171,7 @@ class _CredentialControllers {
|
|||
tag: TextEditingController(text: credential.meta.tag),
|
||||
username: TextEditingController(text: credential.username),
|
||||
email: TextEditingController(text: credential.email),
|
||||
password: TextEditingController(text: credential.password),
|
||||
otpSecret: TextEditingController(text: credential.otpSecret),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import 'package:provider/provider.dart';
|
|||
import '../types/abstracts.dart';
|
||||
import '../types/credential.dart';
|
||||
|
||||
import '../utils/crypto.dart' as crypto;
|
||||
|
||||
import '../widgets/tappable_text_list.dart';
|
||||
|
||||
class Credentials extends StatelessWidget {
|
||||
|
|
@ -20,10 +22,39 @@ class Credentials extends StatelessWidget {
|
|||
}
|
||||
|
||||
Map<String, GestureTapCallback> _buildTappableText(BuildContext context) {
|
||||
var makeOnTapHandler = (String id) => () async {
|
||||
final credential =
|
||||
await Provider.of<CredentialsRepo>(context).get(id);
|
||||
Navigator.of(context).pushNamed('/credential', arguments: credential);
|
||||
final makeOnTapHandler = (String id) => () async {
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||
content: Column(
|
||||
children: [
|
||||
Text('Decrypting credential...'),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 10),
|
||||
child: CupertinoActivityIndicator()),
|
||||
],
|
||||
)),
|
||||
);
|
||||
|
||||
final config = Provider.of<ConfigRepo>(context);
|
||||
final client = Provider.of<CredentialsRepo>(context);
|
||||
|
||||
final Future<String> privateKey = config.privateKey;
|
||||
final String password = config.password;
|
||||
|
||||
final credential = await client.get(id);
|
||||
|
||||
credential.password = crypto.decryptPassword(
|
||||
password, await privateKey, credential.password);
|
||||
|
||||
if (credential.otpSecret != null && credential.otpSecret != '') {
|
||||
credential.otpSecret = crypto.decryptPassword(
|
||||
password, await privateKey, credential.otpSecret);
|
||||
}
|
||||
|
||||
Navigator.of(context)
|
||||
..pop()
|
||||
..pushNamed('/credential', arguments: credential);
|
||||
};
|
||||
|
||||
Map<String, GestureTapCallback> tappableText = {};
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ class _HomeState extends State<Home> {
|
|||
GestureTapCallback _makeConfigOnTapHandler(BuildContext context) {
|
||||
return () async => Navigator.of(context).pushNamed('/config',
|
||||
arguments: ConfigScreenArguments(
|
||||
await _config.connectionConfig, await _config.privateKey));
|
||||
connectionConfig: await _config.connectionConfig,
|
||||
privateKey: await _config.privateKey));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue