mirror of
https://github.com/inventree/inventree-app.git
synced 2025-06-14 11:15:26 +00:00
Token auth (#434)
* Embed device platform information into token request * Remove username and password from userProfile * Display icon to show if profile has associated user token * Remove username / password from login settings screen * Refactor login procedure around token auth * Refactoring * Add profile login screen - Username / password values are not stored - Just to fetch api token * Login with basic auth * Pass profile to API when connecting * Remove _BASE_URL accessor - Fixes URL caching bug * Add more context to login screen * Add helper functions for unit tests - Change default port to 8000 (makes testing easier with local inventree instance) * api.dart handles basic auth now * fix api_test.dart * Further test improvements * linting fixes * Provide feedback when login fails * More linting * Record user details on login, and display in "about" widget * Fix string lookup * Add extra debug * Fix auth values * Fix user profile test
This commit is contained in:
@ -17,37 +17,11 @@ void main() {
|
||||
|
||||
setUp(() async {
|
||||
|
||||
if (! await UserProfileDBManager().profileNameExists("Test Profile")) {
|
||||
// Create and select a profile to user
|
||||
|
||||
print("TEST: Creating profile for user 'testuser'");
|
||||
|
||||
await UserProfileDBManager().addProfile(UserProfile(
|
||||
name: "Test Profile",
|
||||
server: "http://localhost:12345",
|
||||
username: "testuser",
|
||||
password: "testpassword",
|
||||
selected: true,
|
||||
));
|
||||
}
|
||||
|
||||
var prf = await UserProfileDBManager().getSelectedProfile();
|
||||
|
||||
// Ensure that the server settings are correct by default,
|
||||
// as they can get overwritten by subsequent tests
|
||||
|
||||
if (prf != null) {
|
||||
prf.name = "Test Profile";
|
||||
prf.server = "http://localhost:12345";
|
||||
prf.username = "testuser";
|
||||
prf.password = "testpassword";
|
||||
|
||||
await UserProfileDBManager().updateProfile(prf);
|
||||
}
|
||||
await setupServerProfile(select: true);
|
||||
|
||||
// Ensure the profile is selected
|
||||
assert(! await UserProfileDBManager().selectProfileByName("Missing Profile"));
|
||||
assert(await UserProfileDBManager().selectProfileByName("Test Profile"));
|
||||
assert(await UserProfileDBManager().selectProfileByName(testServerName));
|
||||
|
||||
});
|
||||
|
||||
@ -71,53 +45,57 @@ void main() {
|
||||
var api = InvenTreeAPI();
|
||||
|
||||
// Incorrect server address
|
||||
var profile = await UserProfileDBManager().getSelectedProfile();
|
||||
var profile = await setupServerProfile();
|
||||
|
||||
assert(profile != null);
|
||||
profile.server = "http://localhost:5555";
|
||||
|
||||
if (profile != null) {
|
||||
profile.server = "http://localhost:5555";
|
||||
await UserProfileDBManager().updateProfile(profile);
|
||||
bool result = await api.connectToServer(profile);
|
||||
assert(!result);
|
||||
|
||||
bool result = await api.connectToServer();
|
||||
assert(!result);
|
||||
debugContains("SocketException at");
|
||||
|
||||
debugContains("SocketException at");
|
||||
// Test incorrect login details
|
||||
profile.server = testServerAddress;
|
||||
|
||||
// Test incorrect login details
|
||||
profile.server = "http://localhost:12345";
|
||||
profile.username = "invalidusername";
|
||||
final response = await api.fetchToken(profile, "baduser", "badpassword");
|
||||
assert(!response.successful());
|
||||
|
||||
await UserProfileDBManager().updateProfile(profile);
|
||||
debugContains("Token request failed");
|
||||
|
||||
await api.connectToServer();
|
||||
assert(!result);
|
||||
assert(!api.checkConnection());
|
||||
|
||||
debugContains("Token request failed");
|
||||
debugContains("Token request failed: STATUS 401");
|
||||
debugContains("showSnackIcon: 'Not Connected'");
|
||||
|
||||
assert(!api.checkConnection());
|
||||
});
|
||||
|
||||
debugContains("Token request failed: STATUS 401");
|
||||
debugContains("showSnackIcon: 'Not Connected'");
|
||||
test("Bad Token", () async {
|
||||
// Test that login fails with a bad token
|
||||
var profile = await setupServerProfile();
|
||||
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
profile.token = "bad-token";
|
||||
|
||||
bool result = await InvenTreeAPI().connectToServer(profile);
|
||||
assert(!result);
|
||||
});
|
||||
|
||||
test("Login Success", () async {
|
||||
// Test that we can login to the server successfully
|
||||
var api = InvenTreeAPI();
|
||||
|
||||
// Attempt to connect
|
||||
final bool result = await api.connectToServer();
|
||||
final profile = await setupServerProfile(select: true, fetchToken: true);
|
||||
assert(profile.hasToken);
|
||||
|
||||
// Now, connect to the server
|
||||
bool result = await api.connectToServer(profile);
|
||||
|
||||
// Check expected values
|
||||
assert(result);
|
||||
assert(api.hasToken);
|
||||
expect(api.baseUrl, equals("http://localhost:12345/"));
|
||||
|
||||
expect(api.baseUrl, equals(testServerAddress));
|
||||
|
||||
assert(api.hasToken);
|
||||
assert(api.isConnected());
|
||||
assert(!api.isConnecting());
|
||||
assert(api.checkConnection());
|
||||
@ -127,7 +105,8 @@ void main() {
|
||||
// Test server version information
|
||||
var api = InvenTreeAPI();
|
||||
|
||||
assert(await api.connectToServer());
|
||||
final profile = await setupServerProfile(fetchToken: true);
|
||||
assert(await api.connectToServer(profile));
|
||||
|
||||
// Check supported functions
|
||||
assert(api.apiVersion >= 50);
|
||||
@ -135,12 +114,15 @@ void main() {
|
||||
assert(api.supportsNotifications);
|
||||
assert(api.supportsPoReceive);
|
||||
|
||||
// Ensure we can request (and receive) user roles
|
||||
assert(await api.getUserRoles());
|
||||
assert(api.serverInstance.isNotEmpty);
|
||||
assert(api.serverVersion.isNotEmpty);
|
||||
|
||||
// Ensure we can have user role data
|
||||
assert(api.roles.isNotEmpty);
|
||||
|
||||
// Check available permissions
|
||||
assert(api.checkPermission("part", "change"));
|
||||
assert(api.checkPermission("stocklocation", "delete"));
|
||||
assert(api.checkPermission("stock_location", "delete"));
|
||||
assert(!api.checkPermission("part", "weirdpermission"));
|
||||
assert(api.checkPermission("blah", "bloo"));
|
||||
|
||||
|
@ -10,7 +10,6 @@ import "package:flutter_test/flutter_test.dart";
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/barcode/barcode.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/user_profile.dart";
|
||||
|
||||
import "package:inventree/inventree/part.dart";
|
||||
import "package:inventree/inventree/stock.dart";
|
||||
@ -23,26 +22,7 @@ void main() {
|
||||
|
||||
// Connect to the server
|
||||
setUpAll(() async {
|
||||
final prf = await UserProfileDBManager().getProfileByName("Test Profile");
|
||||
|
||||
if (prf != null) {
|
||||
await UserProfileDBManager().deleteProfile(prf);
|
||||
}
|
||||
|
||||
bool result = await UserProfileDBManager().addProfile(
|
||||
UserProfile(
|
||||
name: "Test Profile",
|
||||
server: "http://localhost:12345",
|
||||
username: "testuser",
|
||||
password: "testpassword",
|
||||
selected: true,
|
||||
),
|
||||
);
|
||||
|
||||
assert(result);
|
||||
|
||||
assert(await UserProfileDBManager().selectProfileByName("Test Profile"));
|
||||
assert(await InvenTreeAPI().connectToServer());
|
||||
await connectToTestServer();
|
||||
});
|
||||
|
||||
setUp(() async {
|
||||
@ -91,8 +71,8 @@ void main() {
|
||||
test("Scan Into Location", () async {
|
||||
|
||||
final item = await InvenTreeStockItem().get(1) as InvenTreeStockItem?;
|
||||
|
||||
assert(item != null);
|
||||
|
||||
assert(item!.pk == 1);
|
||||
|
||||
var handler = StockItemScanIntoLocationHandler(item!);
|
||||
|
@ -5,7 +5,6 @@
|
||||
import "package:test/test.dart";
|
||||
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/user_profile.dart";
|
||||
import "package:inventree/inventree/model.dart";
|
||||
import "package:inventree/inventree/part.dart";
|
||||
|
||||
@ -16,16 +15,7 @@ void main() {
|
||||
setupTestEnv();
|
||||
|
||||
setUp(() async {
|
||||
await UserProfileDBManager().addProfile(UserProfile(
|
||||
name: "Test Profile",
|
||||
server: "http://localhost:12345",
|
||||
username: "testuser",
|
||||
password: "testpassword",
|
||||
selected: true,
|
||||
));
|
||||
|
||||
assert(await UserProfileDBManager().selectProfileByName("Test Profile"));
|
||||
assert(await InvenTreeAPI().connectToServer());
|
||||
await connectToTestServer();
|
||||
});
|
||||
|
||||
group("Category Tests:", () {
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/user_profile.dart";
|
||||
|
||||
// This is the same as the following issue except it keeps the http client
|
||||
// TestWidgetsFlutterBinding.ensureInitialized();
|
||||
@ -19,4 +21,78 @@ void setupTestEnv() {
|
||||
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
|
||||
return ".";
|
||||
});
|
||||
}
|
||||
|
||||
// Accessors for default testing values
|
||||
const String testServerAddress = "http://localhost:8000/";
|
||||
const String testServerName = "Test Server";
|
||||
const String testUsername = "testuser";
|
||||
const String testPassword = "testpassword";
|
||||
|
||||
|
||||
/*
|
||||
* Request an API token for the given profile
|
||||
*/
|
||||
Future<bool> fetchProfileToken({
|
||||
UserProfile? profile,
|
||||
String username = testUsername,
|
||||
String password = testPassword
|
||||
}) async {
|
||||
|
||||
profile ??= await UserProfileDBManager().getProfileByName(testServerName);
|
||||
|
||||
assert(profile != null);
|
||||
|
||||
final response = await InvenTreeAPI().fetchToken(profile!, username, password);
|
||||
return response.successful();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup a valid profile, and return it
|
||||
*/
|
||||
Future<UserProfile> setupServerProfile({bool select = true, bool fetchToken = false}) async {
|
||||
// Setup a valid server profile
|
||||
|
||||
UserProfile? profile = await UserProfileDBManager().getProfileByName(testServerName);
|
||||
|
||||
if (profile == null) {
|
||||
// Profile does not already exist - create it!
|
||||
bool result = await UserProfileDBManager().addProfile(
|
||||
UserProfile(
|
||||
server: testServerAddress,
|
||||
name: testServerName
|
||||
)
|
||||
);
|
||||
|
||||
assert(result);
|
||||
}
|
||||
|
||||
profile = await UserProfileDBManager().getProfileByName(testServerName);
|
||||
assert(profile != null);
|
||||
|
||||
if (select) {
|
||||
assert(await UserProfileDBManager().selectProfileByName(testServerName));
|
||||
}
|
||||
|
||||
if (fetchToken && !profile!.hasToken) {
|
||||
final bool result = await fetchProfileToken(profile: profile);
|
||||
assert(result);
|
||||
assert(profile.hasToken);
|
||||
}
|
||||
|
||||
return profile!;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Complete all steps necessary to login to the server
|
||||
*/
|
||||
Future<void> connectToTestServer() async {
|
||||
|
||||
// Setup profile, and fetch user token as necessary
|
||||
final profile = await setupServerProfile(fetchToken: true);
|
||||
|
||||
// Connect to the server
|
||||
assert(await InvenTreeAPI().connectToServer(profile));
|
||||
}
|
@ -27,10 +27,8 @@ void main() {
|
||||
|
||||
// Now, create one!
|
||||
bool result = await UserProfileDBManager().addProfile(UserProfile(
|
||||
name: "Test Profile",
|
||||
username: "testuser",
|
||||
password: "testpassword""",
|
||||
server: "http://localhost:12345",
|
||||
name: testServerName,
|
||||
server: testServerAddress,
|
||||
selected: true,
|
||||
));
|
||||
|
||||
@ -62,20 +60,15 @@ void main() {
|
||||
test("Add Invalid Profiles", () async {
|
||||
// Add a profile with missing data
|
||||
bool result = await UserProfileDBManager().addProfile(
|
||||
UserProfile(
|
||||
username: "what",
|
||||
password: "why",
|
||||
)
|
||||
UserProfile()
|
||||
);
|
||||
|
||||
expect(result, equals(false));
|
||||
|
||||
// Add a profile with a name that already exists
|
||||
// Add a profile with a new name
|
||||
result = await UserProfileDBManager().addProfile(
|
||||
UserProfile(
|
||||
name: "Test Profile",
|
||||
username: "xyz",
|
||||
password: "hunter42",
|
||||
name: "Another Test Profile",
|
||||
)
|
||||
);
|
||||
|
||||
@ -84,14 +77,14 @@ void main() {
|
||||
// Check that the number of protocols available is still the same
|
||||
var profiles = await UserProfileDBManager().getAllProfiles();
|
||||
|
||||
expect(profiles.length, equals(1));
|
||||
expect(profiles.length, equals(2));
|
||||
});
|
||||
|
||||
test("Profile Name Check", () async {
|
||||
bool result = await UserProfileDBManager().profileNameExists("doesnotexist");
|
||||
expect(result, equals(false));
|
||||
|
||||
result = await UserProfileDBManager().profileNameExists("Test Profile");
|
||||
result = await UserProfileDBManager().profileNameExists("Test Server");
|
||||
expect(result, equals(true));
|
||||
});
|
||||
|
||||
@ -104,23 +97,16 @@ void main() {
|
||||
if (prf != null) {
|
||||
UserProfile p = prf;
|
||||
|
||||
expect(p.name, equals("Test Profile"));
|
||||
expect(p.username, equals("testuser"));
|
||||
expect(p.password, equals("testpassword"));
|
||||
expect(p.server, equals("http://localhost:12345"));
|
||||
expect(p.name, equals(testServerName));
|
||||
expect(p.server, equals(testServerAddress));
|
||||
|
||||
expect(p.toString(), equals("<${p.key}> Test Profile : http://localhost:12345 - testuser:testpassword"));
|
||||
expect(p.toString(), equals("<${p.key}> Test Server : http://localhost:8000/"));
|
||||
|
||||
// Test that we can update the profile
|
||||
p.name = "different name";
|
||||
|
||||
bool result = await UserProfileDBManager().updateProfile(p);
|
||||
expect(result, equals(true));
|
||||
|
||||
// Trying to update with an invalid value will fail!
|
||||
p.password = "";
|
||||
result = await UserProfileDBManager().updateProfile(p);
|
||||
expect(result, equals(false));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user