From cdc04a340173a70abefbde03b7af79a00c0adfb7 Mon Sep 17 00:00:00 2001 From: blallo Date: Sun, 18 Aug 2019 18:04:39 -0300 Subject: [PATCH] Added utils to connect to server. --- lib/connection.dart | 84 ----------------- lib/utils/connection.dart | 189 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 84 deletions(-) delete mode 100644 lib/connection.dart create mode 100644 lib/utils/connection.dart diff --git a/lib/connection.dart b/lib/connection.dart deleted file mode 100644 index 62c4a08..0000000 --- a/lib/connection.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:http/http.dart'; -import 'package:logger/logger.dart'; -import 'dart:convert'; - - -final log = Logger(); - - -class Connection { - // Connection constructor. - Connection(this.username, this.password, this.baseAddress); - // baseAddress contains the base address to the BotZ server - // assuming that the APIs are located at /api/. - final String baseAddress; - // Username is the username to autenticate against the foreign - // service. - final String username; - // Password is the password to autenticate against the foreign - // service. - final String password; - // _stateCookie is private. It contains the HTTP state cookie - // assigned by the server. - String _stateCookie = ""; - bool _loggedIn = false; - - - void login() async { - // TODO: perform the login and obtain the cookie. Set the - // _loggedIn state accordingly. - } - void logout() async { - // TODO: perform the logout. If successful, empty the _stateCookie - // and set the _loggedIn state accordingly. - } - void checkin() async { - // TODO: perform the checkin if possible. - } - void checkout() async { - // TODO: perform the checkout if possible. - } - Future> getMovements() async { - // TODO: query /api/movements and retrieve the list of movements. - return {}; - } -} - - -class UnauthorizedException implements ClientException { - UnauthorizedException(this.uri); - final String message = "Unauthorized"; - final Uri uri; -} - - -Response handleResponse(Response resp) { - final c = resp.statusCode; - if (c >= 200 && c < 400) { - } else if (c == 401) { - throw UnauthorizedException(resp.request.url); - } else if (c >=400 || c < 500) { - throw ClientException("Unexpected return code: $c", resp.request.url); - } else if (c >= 500) { - throw ClientException("Server error: $c", resp.request.url); - } - return resp; -} - - -class BotZContent { - BotZContent(this.response) { - this.response.then((resp) => handleResponse(resp)) - .then((value) => this.initContent(value)) - .catchError((err) => log.e(err)); - } - final Future response; - Map body; - List cookies; - - void initContent(Response resp) { - this.cookies = resp.headers['cookies'].split(';'); - this.body = jsonDecode(resp.body); - } -} - diff --git a/lib/utils/connection.dart b/lib/utils/connection.dart new file mode 100644 index 0000000..af7cc0f --- /dev/null +++ b/lib/utils/connection.dart @@ -0,0 +1,189 @@ +import 'package:http/http.dart'; +import 'package:logger/logger.dart'; +import 'dart:convert'; + + +final log = Logger(); +const defaultRoutes = { + "login": "/api/login", + "logout": "/api/logout", + "checkin": "/api/checkin", + "checkout": "/api/checkout", + "movements": "/api/movements", + "status": "/api/status", + "ping": "/api/ping", +}; + + +class Connection { + // Connection constructor. + Connection(this.username, this.password, this.baseAddress, [this.routes = defaultRoutes]); + // baseAddress contains the base address to the BotZ server + final Uri baseAddress; + // Username is the username to autenticate against the foreign + // service. + final String username; + // Password is the password to autenticate against the foreign + // service. + final String password; + final Map routes; + // _stateCookie is private. It contains the HTTP state cookie + // assigned by the server. + String _cookies = ""; + bool _loggedIn = false; + bool _checkedIn = false; + + void updateState(String cookies, bool loggedIn) { + this._cookies = loggedIn ? cookies : ""; + this._loggedIn = loggedIn; + } + + void updateMovement(bool checkedIn) => this._checkedIn = checkedIn; + + bool isLoggedIn() => this._loggedIn; + + bool isCheckedIn() => this._checkedIn; + + // Perform the login and obtain the cookie. + void login() async { + var targetUri = this.baseAddress.toString() + this.routes['login']; + var payload = jsonEncode({ + "username": this.username, + "password": this.password, + }); + + var resp = await post( + targetUri, + headers: {"Content-Type": "application/json"}, + body: payload, + ); + + log.d("[login] Post sent to: $targetUri"); + handleResponse(resp); + var body = jsonDecode(resp.body); + log.d("[login] Response: $body"); + this.updateState(resp.headers['cookies'], body['logged_in']); + } + + // Perform the logout. + void logout() async { + var targetUri = this.baseAddress.toString() + this.routes['logout']; + + var resp = await post( + targetUri, + headers: {'cookies': this._cookies}, + ); + + log.d("[logout] Post sent to: $targetUri"); + handleResponse(resp); + var body = jsonDecode(resp.body); + log.d("[logout] Response: $body"); + this.updateState(this._cookies, body['logged_in']); + } + + // Perform the checkin if possible. + void checkin() async { + if (!this._loggedIn) { + throw UnacceptableInvocationException("Not logged in"); + } + if (this._checkedIn) { + throw UnacceptableInvocationException("Yet checked in"); + } + var targetUri = this.baseAddress.toString() + this.routes['checkin']; + + var resp = await post( + targetUri, + headers: {'cookies': this._cookies}, + ); + + handleResponse(resp); + var body = jsonDecode(resp.body); + log.d("[checkin] Response: $body"); + this.updateMovement(body['checked_in']); + } + + // Perform the checkout if possible. + void checkout() async { + if (!this._loggedIn) { + throw UnacceptableInvocationException("Not logged in"); + } + if (!this._checkedIn) { + throw UnacceptableInvocationException("Not yet checked in"); + } + var targetUri = this.baseAddress.toString() + this.routes['checkout']; + + var resp = await post( + targetUri, + headers: {'cookies': this._cookies}, + ); + + handleResponse(resp); + var body = jsonDecode(resp.body); + log.d("[checkout] Response: $body"); + this.updateMovement(body['checked_in']); + } + + // Query the server for the list of movements. + Future> getMovements() async { + if (!this._loggedIn) { + throw UnacceptableInvocationException("Not logged in"); + } + if (!this._checkedIn) { + throw UnacceptableInvocationException("Not yet checked in"); + } + var targetUri = this.baseAddress.toString() + this.routes['movements']; + + var resp = await get( + targetUri, + headers: {'cookies': this._cookies}, + ); + + try { + handleResponse(resp); + } on NotFoundException { + return {}; + } + var body = jsonDecode(resp.body); + Map movements; + for (var values in body['movements']) { + movements[values['time']] = values['type']; + } + return movements; + } +} + + +class UnauthorizedException implements ClientException { + UnauthorizedException(this.uri); + final String message = "Unauthorized"; + final Uri uri; +} + + +class NotFoundException implements ClientException { + NotFoundException(this.uri); + final String message = "Resource not found"; + final Uri uri; +} + + +class UnacceptableInvocationException implements Exception { + UnacceptableInvocationException(this.message); + final String message; +} + + +Response handleResponse(Response resp) { + final c = resp.statusCode; + if (c >= 200 && c < 400) { + } else if (c == 401) { + throw UnauthorizedException(resp.request.url); + } else if (c == 404) { + throw NotFoundException(resp.request.url); + }else if (c >=400 || c < 500) { + throw ClientException("Unexpected return code: $c", resp.request.url); + } else if (c >= 500) { + throw ClientException("Server error: $c", resp.request.url); + } + return resp; +}