Added server data form.

master
blallo 2019-08-18 18:06:25 -03:00
parent 7e9d90b9f7
commit 1868f4e722
Signed by: blallo
GPG Key ID: 0CBE577C9B72DC3F
5 changed files with 217 additions and 6 deletions

View File

@ -1,21 +1,29 @@
import 'package:flutter/material.dart';
import 'ui/server_form.dart';
import 'ui/dialog.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final title = 'Welcome page test';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
title: title,
theme: ThemeData(
primarySwatch: Colors.green,
dialogTheme: baseDialogTheme,
),
home: Scaffold(
appBar: AppBar(title: Text(title)),
body: ServerForm(),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

View File

@ -0,0 +1,153 @@
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'dart:convert';
import 'dialog.dart';
import '../utils/verify_server.dart';
final log = Logger();
class ServerForm extends StatefulWidget {
ServerForm({Key key}) : super(key: key);
@override
_ServerFormState createState() => _ServerFormState();
}
class _ServerFormState extends State<ServerForm> {
Uri zAddress;
Uri botZAddress;
bool _autoValidate = false;
bool _disableFields = false;
final _serverFormKey = GlobalKey<FormState>();
final zController = TextEditingController();
final botZController = TextEditingController();
InputDecoration _textFieldDecoration(String label, IconData icon) {
return InputDecoration(
labelText: label,
icon: Icon(icon),
hintText: 'Please, insert $label address',
);
}
SnackBar showProgress() {
return SnackBar(
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircularProgressIndicator(
value: null,
strokeWidth: 7.0,
),
Text('Processing Data')
],
));
}
String validateServer(String address) {
if (address.isEmpty) {
return 'Server address must not be empty';
}
try {
Uri.parse(address);
} on FormatException catch (e) {
return e.toString();
}
return null;
}
String validateZServer(String address) {
String baseValidation = this.validateServer(address);
if (baseValidation != null) {
return baseValidation;
}
if (utf8.encode(address).length > 72) {
return "Server address string length is > 72 bytes. Refusing to go on.";
}
return null;
}
Future<void> _onPressed() async {
log.d("Button pressed");
setState(() {
_disableFields = true;
});
Scaffold.of(context).showSnackBar(this.showProgress());
if (!_serverFormKey.currentState.validate()) {
setState(() {
_autoValidate = true;
_disableFields = false;
});
Scaffold.of(context).hideCurrentSnackBar();
return;
}
bool resp;
Uri _botZAddr = Uri.parse(botZController.text);
Uri _zAddr = Uri.parse(zController.text);
log.d("Received botZAddr: $_botZAddr\tzAddr: $_zAddr");
try {
resp = await verifyServer(_botZAddr, _zAddr);
log.i("Secret is${resp ? ' ' : ' NOT '}a match");
} catch (err) {
log.e("Error: ${err.toString()}");
showDialog(
context: context,
builder: errorDialogBuilder("Error", "${err.toString()}"));
} finally {
log.d("Clean the state");
setState(() {
_disableFields = false;
});
Scaffold.of(context).hideCurrentSnackBar();
}
if (!resp) {
showDialog(
context: context,
builder: errorDialogBuilder("Error",
"The BotZ server does not target the provided Z server."));
} else {
_serverFormKey.currentState.save();
// TODO: go to the next window.
}
log.d("Done");
}
@override
Widget build(BuildContext context) {
return Form(
key: _serverFormKey,
child: Column(children: <Widget>[
TextFormField(
autofocus: true,
autocorrect: false,
controller: zController,
enabled: !_disableFields,
decoration: this._textFieldDecoration("Z server", Icons.http),
validator: this.validateZServer,
autovalidate: _autoValidate,
onSaved: (String addr) {
zAddress = Uri.parse(addr);
}),
TextFormField(
autocorrect: false,
controller: botZController,
enabled: !_disableFields,
decoration: this._textFieldDecoration("BotZ server", Icons.http),
validator: this.validateServer,
autovalidate: _autoValidate,
onSaved: (String addr) {
botZAddress = Uri.parse(addr);
}),
RaisedButton(
onPressed: _onPressed,
child: Text('Save'),
),
]),
);
}
}

View File

@ -0,0 +1,42 @@
import 'package:http/http.dart';
import 'package:logger/logger.dart';
import 'dart:convert';
import 'package:dbcrypt/dbcrypt.dart';
import 'connection.dart';
final log = Logger();
Future<bool> verifyServer(Uri serverAddr, Uri zTargetAddr, {Map<String, String> routes=defaultRoutes}) async {
String botZTargetUri = serverAddr.toString() + routes['ping'];
log.d("botZ server uri: $botZTargetUri");
log.d("z server: ${zTargetAddr.toString()}");
var resp = await get(
botZTargetUri,
);
log.d("Status code: ${resp.statusCode}");
if (resp.statusCode >= 300 || resp.statusCode < 200) {
log.d("Status code is not 2xx: $resp.statusCode");
return false;
}
Map<String, dynamic> respData = jsonDecode(resp.body);
log.d("Response: ${respData.toString()}");
if (!respData.containsKey('hash')) {
log.d("Response is malformed: ${respData.toString()}");
return false;
}
if (!DBCrypt().checkpw(zTargetAddr.toString(), respData['hash'])) {
log.d("The server answer do not match the expected response: ${respData.toString()}");
return false;
}
log.d("Response is ok!");
return true;
}

View File

@ -36,6 +36,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
dbcrypt:
dependency: "direct main"
description:
name: dbcrypt
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter:
dependency: "direct main"
description: flutter

View File

@ -22,6 +22,7 @@ dependencies:
http: ^0.12.0+2
logger: ^0.7.0+2
dbcrypt: ^1.0.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2