mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 21:46:46 +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();
|
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 {
|
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;
|
if (profile == null) return false;
|
||||||
|
|
||||||
|
var ctx = OneContext().context;
|
||||||
|
|
||||||
String address = profile.server.trim();
|
String address = profile.server.trim();
|
||||||
String username = profile.username.trim();
|
String username = profile.username.trim();
|
||||||
String password = profile.password.trim();
|
String password = profile.password.trim();
|
||||||
|
|
||||||
if (address.isEmpty || username.isEmpty || password.isEmpty) {
|
if (address.isEmpty || username.isEmpty || password.isEmpty) {
|
||||||
showSnackIcon(
|
showSnackIcon(
|
||||||
"Incomplete server details",
|
"Incomplete profile details",
|
||||||
icon: FontAwesomeIcons.exclamationCircle,
|
icon: FontAwesomeIcons.exclamationCircle,
|
||||||
success: false
|
success: false
|
||||||
);
|
);
|
||||||
@ -189,28 +195,36 @@ class InvenTreeAPI {
|
|||||||
if (!address.endsWith('/')) {
|
if (!address.endsWith('/')) {
|
||||||
address = address + '/';
|
address = address + '/';
|
||||||
}
|
}
|
||||||
|
/* TODO: Better URL validation
|
||||||
// TODO - Better URL validation
|
|
||||||
|
|
||||||
/*
|
|
||||||
* - If not a valid URL, return error
|
* - If not a valid URL, return error
|
||||||
* - If no port supplied, append a default port
|
* - If no port supplied, append a default port
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_BASE_URL = address;
|
_BASE_URL = address;
|
||||||
|
|
||||||
print("Connecting to ${apiUrl} -> ${username}:${password}");
|
print("Connecting to ${apiUrl} -> username=${username}");
|
||||||
|
|
||||||
// Request the /api/ endpoint - response is a json object
|
HttpClientResponse response;
|
||||||
var response = await get("");
|
dynamic data;
|
||||||
|
|
||||||
|
response = await getResponse("");
|
||||||
|
|
||||||
// Null response means something went horribly wrong!
|
// Null response means something went horribly wrong!
|
||||||
|
// Most likely, the server cannot be contacted
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
|
// An error message has already been displayed!
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
showStatusCodeError(response.statusCode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = await responseToJson(response);
|
||||||
|
|
||||||
// We expect certain response from the server
|
// 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(
|
showServerError(
|
||||||
"Missing Data",
|
"Missing Data",
|
||||||
@ -221,16 +235,14 @@ class InvenTreeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Record server information
|
// Record server information
|
||||||
_version = response["version"];
|
_version = data["version"];
|
||||||
instance = response['instance'] ?? '';
|
instance = data['instance'] ?? '';
|
||||||
|
|
||||||
// Default API version is 1 if not provided
|
// Default API version is 1 if not provided
|
||||||
_apiVersion = response['apiVersion'] as int ?? 1;
|
_apiVersion = data['apiVersion'] as int ?? 1;
|
||||||
|
|
||||||
if (_apiVersion < _minApiVersion) {
|
if (_apiVersion < _minApiVersion) {
|
||||||
|
|
||||||
BuildContext ctx = OneContext().context;
|
|
||||||
|
|
||||||
String message = I18N.of(ctx).serverApiVersion + ": ${_apiVersion}";
|
String message = I18N.of(ctx).serverApiVersion + ": ${_apiVersion}";
|
||||||
|
|
||||||
message += "\n";
|
message += "\n";
|
||||||
@ -248,23 +260,43 @@ class InvenTreeAPI {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request user token information from the server
|
||||||
|
* This is the stage that we check username:password credentials!
|
||||||
|
*/
|
||||||
// Clear the existing token value
|
// Clear the existing token value
|
||||||
_token = "";
|
_token = "";
|
||||||
|
|
||||||
print("Requesting token from server");
|
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) {
|
if (response == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
|
||||||
|
switch (response.statusCode) {
|
||||||
|
case 401:
|
||||||
|
case 403:
|
||||||
showServerError(
|
showServerError(
|
||||||
I18N.of(OneContext().context).tokenError,
|
I18N.of(ctx).serverAuthenticationError,
|
||||||
"Error requesting access token from server"
|
"Incorrect username:password combination"
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
showStatusCodeError(response.statusCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.containsKey("token")) {
|
data = await responseToJson(response);
|
||||||
|
|
||||||
|
if (data == null || !data.containsKey("token")) {
|
||||||
showServerError(
|
showServerError(
|
||||||
I18N.of(OneContext().context).tokenMissing,
|
I18N.of(OneContext().context).tokenMissing,
|
||||||
"Access token missing from response"
|
"Access token missing from response"
|
||||||
@ -274,7 +306,7 @@ class InvenTreeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the received token
|
// Return the received token
|
||||||
_token = response["token"];
|
_token = data["token"];
|
||||||
print("Received token - $_token");
|
print("Received token - $_token");
|
||||||
|
|
||||||
// Request user role information
|
// Request user role information
|
||||||
@ -420,7 +452,7 @@ class InvenTreeAPI {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Request could not be made
|
// Request could not be made
|
||||||
if (request = null) {
|
if (request == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +506,9 @@ class InvenTreeAPI {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
var responseData = await responseToJson(response);
|
||||||
|
|
||||||
|
return responseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -591,25 +625,9 @@ class InvenTreeAPI {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the body of the response to a JSON object
|
var responseData = await responseToJson(response);
|
||||||
String responseData = await response.transform(utf8.decoder).join();
|
|
||||||
|
|
||||||
try {
|
return responseData;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpClient createClient(bool allowBadCert) {
|
HttpClient createClient(bool allowBadCert) {
|
||||||
@ -641,10 +659,11 @@ class InvenTreeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a HTTP GET request
|
* Perform a HTTP GET request,
|
||||||
* Returns a json object (or null if did not complete)
|
* 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);
|
var _url = makeApiUrl(url);
|
||||||
|
|
||||||
print("GET: ${_url}");
|
print("GET: ${_url}");
|
||||||
@ -700,8 +719,6 @@ class InvenTreeAPI {
|
|||||||
request.headers.set(HttpHeaders.contentTypeHeader, 'application/json');
|
request.headers.set(HttpHeaders.contentTypeHeader, 'application/json');
|
||||||
request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader());
|
request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader());
|
||||||
|
|
||||||
print("Attempting connection");
|
|
||||||
|
|
||||||
HttpClientResponse response = await request.close()
|
HttpClientResponse response = await request.close()
|
||||||
.timeout(Duration(seconds: 10))
|
.timeout(Duration(seconds: 10))
|
||||||
.catchError((error) {
|
.catchError((error) {
|
||||||
@ -728,28 +745,21 @@ class InvenTreeAPI {
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
print("got here");
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic responseToJson(HttpClientResponse response) async {
|
||||||
|
|
||||||
// A null response means something has gone wrong...
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
print("null response from GET ${_url}");
|
|
||||||
return null;
|
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();
|
String body = await response.transform(utf8.decoder).join();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var data = json.decode(body);
|
var data = json.decode(body);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
} on FormatException {
|
} on FormatException {
|
||||||
|
|
||||||
print("JSON format exception!");
|
print("JSON format exception!");
|
||||||
@ -761,6 +771,32 @@ class InvenTreeAPI {
|
|||||||
);
|
);
|
||||||
return null;
|
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() {
|
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