mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 13:36:50 +00:00
Driving the refactor tractor
- Separated get into getRequest and get - Improved login error messages
This commit is contained in:
parent
f5e1f25dd0
commit
8a6be4142a
154
lib/api.dart
154
lib/api.dart
@ -165,21 +165,27 @@ class InvenTreeAPI {
|
||||
|
||||
InvenTreeAPI._internal();
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the remote InvenTree server:
|
||||
*
|
||||
* - Check that the InvenTree server exists
|
||||
* - Request user token from the server
|
||||
* - Request user roles from the server
|
||||
*/
|
||||
Future<bool> _connect(BuildContext context) async {
|
||||
|
||||
/* Address is the base address for the InvenTree server,
|
||||
* e.g. http://127.0.0.1:8000
|
||||
*/
|
||||
|
||||
if (profile == null) return false;
|
||||
|
||||
var ctx = OneContext().context;
|
||||
|
||||
String address = profile.server.trim();
|
||||
String username = profile.username.trim();
|
||||
String password = profile.password.trim();
|
||||
|
||||
if (address.isEmpty || username.isEmpty || password.isEmpty) {
|
||||
showSnackIcon(
|
||||
"Incomplete server details",
|
||||
"Incomplete profile details",
|
||||
icon: FontAwesomeIcons.exclamationCircle,
|
||||
success: false
|
||||
);
|
||||
@ -189,28 +195,36 @@ class InvenTreeAPI {
|
||||
if (!address.endsWith('/')) {
|
||||
address = address + '/';
|
||||
}
|
||||
|
||||
// TODO - Better URL validation
|
||||
|
||||
/*
|
||||
/* TODO: Better URL validation
|
||||
* - If not a valid URL, return error
|
||||
* - If no port supplied, append a default port
|
||||
*/
|
||||
|
||||
_BASE_URL = address;
|
||||
|
||||
print("Connecting to ${apiUrl} -> ${username}:${password}");
|
||||
print("Connecting to ${apiUrl} -> username=${username}");
|
||||
|
||||
// Request the /api/ endpoint - response is a json object
|
||||
var response = await get("");
|
||||
HttpClientResponse response;
|
||||
dynamic data;
|
||||
|
||||
response = await getResponse("");
|
||||
|
||||
// Null response means something went horribly wrong!
|
||||
// Most likely, the server cannot be contacted
|
||||
if (response == null) {
|
||||
// An error message has already been displayed!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
showStatusCodeError(response.statusCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
data = await responseToJson(response);
|
||||
|
||||
// We expect certain response from the server
|
||||
if (!response.containsKey("server") || !response.containsKey("version") || !response.containsKey("instance")) {
|
||||
if (data == null || !data.containsKey("server") || !data.containsKey("version") || !data.containsKey("instance")) {
|
||||
|
||||
showServerError(
|
||||
"Missing Data",
|
||||
@ -221,16 +235,14 @@ class InvenTreeAPI {
|
||||
}
|
||||
|
||||
// Record server information
|
||||
_version = response["version"];
|
||||
instance = response['instance'] ?? '';
|
||||
_version = data["version"];
|
||||
instance = data['instance'] ?? '';
|
||||
|
||||
// Default API version is 1 if not provided
|
||||
_apiVersion = response['apiVersion'] as int ?? 1;
|
||||
_apiVersion = data['apiVersion'] as int ?? 1;
|
||||
|
||||
if (_apiVersion < _minApiVersion) {
|
||||
|
||||
BuildContext ctx = OneContext().context;
|
||||
|
||||
String message = I18N.of(ctx).serverApiVersion + ": ${_apiVersion}";
|
||||
|
||||
message += "\n";
|
||||
@ -248,23 +260,43 @@ class InvenTreeAPI {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request user token information from the server
|
||||
* This is the stage that we check username:password credentials!
|
||||
*/
|
||||
// Clear the existing token value
|
||||
_token = "";
|
||||
|
||||
print("Requesting token from server");
|
||||
|
||||
response = await get(_URL_GET_TOKEN);
|
||||
response = await getResponse(_URL_GET_TOKEN);
|
||||
|
||||
// A "null" response means that the request was unsuccessful
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
|
||||
switch (response.statusCode) {
|
||||
case 401:
|
||||
case 403:
|
||||
showServerError(
|
||||
I18N.of(OneContext().context).tokenError,
|
||||
"Error requesting access token from server"
|
||||
I18N.of(ctx).serverAuthenticationError,
|
||||
"Incorrect username:password combination"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
showStatusCodeError(response.statusCode);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.containsKey("token")) {
|
||||
data = await responseToJson(response);
|
||||
|
||||
if (data == null || !data.containsKey("token")) {
|
||||
showServerError(
|
||||
I18N.of(OneContext().context).tokenMissing,
|
||||
"Access token missing from response"
|
||||
@ -274,7 +306,7 @@ class InvenTreeAPI {
|
||||
}
|
||||
|
||||
// Return the received token
|
||||
_token = response["token"];
|
||||
_token = data["token"];
|
||||
print("Received token - $_token");
|
||||
|
||||
// Request user role information
|
||||
@ -420,7 +452,7 @@ class InvenTreeAPI {
|
||||
});
|
||||
|
||||
// Request could not be made
|
||||
if (request = null) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -474,7 +506,9 @@ class InvenTreeAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
var responseData = await responseToJson(response);
|
||||
|
||||
return responseData;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -591,25 +625,9 @@ class InvenTreeAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert the body of the response to a JSON object
|
||||
String responseData = await response.transform(utf8.decoder).join();
|
||||
var responseData = await responseToJson(response);
|
||||
|
||||
try {
|
||||
var data = json.decode(responseData);
|
||||
|
||||
return data;
|
||||
|
||||
} on FormatException {
|
||||
|
||||
print("JSON format exception!");
|
||||
print("${responseData}");
|
||||
|
||||
showServerError(
|
||||
"Format Exception",
|
||||
"JSON data format exception:\n${responseData}"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
return responseData;
|
||||
}
|
||||
|
||||
HttpClient createClient(bool allowBadCert) {
|
||||
@ -641,10 +659,11 @@ class InvenTreeAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a HTTP GET request
|
||||
* Returns a json object (or null if did not complete)
|
||||
* Perform a HTTP GET request,
|
||||
* and return the Response object
|
||||
* (or null if the request fails)
|
||||
*/
|
||||
Future<dynamic> get(String url, {Map<String, String> params, int expectedStatusCode=200}) async {
|
||||
Future<HttpClientResponse> getResponse(String url, {Map<String, String> params}) async {
|
||||
var _url = makeApiUrl(url);
|
||||
|
||||
print("GET: ${_url}");
|
||||
@ -700,8 +719,6 @@ class InvenTreeAPI {
|
||||
request.headers.set(HttpHeaders.contentTypeHeader, 'application/json');
|
||||
request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader());
|
||||
|
||||
print("Attempting connection");
|
||||
|
||||
HttpClientResponse response = await request.close()
|
||||
.timeout(Duration(seconds: 10))
|
||||
.catchError((error) {
|
||||
@ -728,28 +745,21 @@ class InvenTreeAPI {
|
||||
return null;
|
||||
});
|
||||
|
||||
print("got here");
|
||||
return response;
|
||||
}
|
||||
|
||||
dynamic responseToJson(HttpClientResponse response) async {
|
||||
|
||||
// A null response means something has gone wrong...
|
||||
if (response == null) {
|
||||
print("null response from GET ${_url}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check the status code of the response
|
||||
if (response.statusCode != expectedStatusCode) {
|
||||
showStatusCodeError(response.statusCode);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert the body of the response to a JSON object
|
||||
String body = await response.transform(utf8.decoder).join();
|
||||
|
||||
try {
|
||||
var data = json.decode(body);
|
||||
|
||||
return data;
|
||||
|
||||
} on FormatException {
|
||||
|
||||
print("JSON format exception!");
|
||||
@ -761,6 +771,32 @@ class InvenTreeAPI {
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a HTTP GET request
|
||||
* Returns a json object (or null if did not complete)
|
||||
*/
|
||||
Future<dynamic> get(String url, {Map<String, String> params, int expectedStatusCode=200}) async {
|
||||
|
||||
var response = await getResponse(url, params: params);
|
||||
|
||||
// A null response means something has gone wrong...
|
||||
if (response == null) {
|
||||
print("null response from GET ${url}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check the status code of the response
|
||||
if (response.statusCode != expectedStatusCode) {
|
||||
showStatusCodeError(response.statusCode);
|
||||
return null;
|
||||
}
|
||||
|
||||
var data = await responseToJson(response);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Map<String, String> defaultHeaders() {
|
||||
|
2
lib/l10n
2
lib/l10n
@ -1 +1 @@
|
||||
Subproject commit 385c15b1e3275140c1b8a4e59de9513a6241dd9b
|
||||
Subproject commit 8c2bf9e993d5c618a0a7b5cb94d189b89d70cbe9
|
Loading…
x
Reference in New Issue
Block a user