mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 13:25:40 +00:00 
			
		
		
		
	Company create (#610)
* API: refactor checkPermission - Rename to checkRole (actually what it is doing) - Permission check will be incoming * Add checkPermission function for API * Create a new company * Bump release notes * Cleanup * Fix
This commit is contained in:
		| @@ -1,3 +1,8 @@ | ||||
| ### 0.18.0 - February 2025 | ||||
| --- | ||||
| - Adds ability to create new companies from the app | ||||
| - Updated translations | ||||
|  | ||||
| ### 0.17.4 - January 2025 | ||||
| --- | ||||
| - Display responsible owner for orders | ||||
|   | ||||
							
								
								
									
										79
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								lib/api.dart
									
									
									
									
									
								
							| @@ -237,9 +237,12 @@ class InvenTreeAPI { | ||||
|  | ||||
|   UserProfile? profile; | ||||
|  | ||||
|   // Available user roles (permissions) are loaded when connecting to the server | ||||
|   // Available user roles are loaded when connecting to the server | ||||
|   Map<String, dynamic> roles = {}; | ||||
|  | ||||
|   // Available user permissions are loaded when connecting to the server | ||||
|   Map<String, dynamic> permissions = {}; | ||||
|  | ||||
|   // Profile authentication token | ||||
|   String get token => profile?.token ?? ""; | ||||
|  | ||||
| @@ -701,12 +704,11 @@ class InvenTreeAPI { | ||||
|  | ||||
|     var data = response.asMap(); | ||||
|  | ||||
|     if (data.containsKey("roles")) { | ||||
|       // Save a local copy of the user roles | ||||
|       roles = (response.data["roles"] ?? {}) as Map<String, dynamic>; | ||||
|     if (!data.containsKey("roles")) { | ||||
|  | ||||
|       roles = {}; | ||||
|       permissions = {}; | ||||
|  | ||||
|       return true; | ||||
|     } else { | ||||
|       showServerError( | ||||
|         apiUrl, | ||||
|         L10().serverError, | ||||
| @@ -714,6 +716,11 @@ class InvenTreeAPI { | ||||
|       ); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     roles = (data["roles"] ?? {}) as Map<String, dynamic>; | ||||
|     permissions = (data["permissions"] ?? {}) as Map<String, dynamic>; | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   // Request plugin information from the server | ||||
| @@ -740,9 +747,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|   /* | ||||
|    * Check if the user has the given role.permission assigned | ||||
|    * e.g. "part", "change" | ||||
|    * e.g. "sales_order", "change" | ||||
|    */ | ||||
|   bool checkPermission(String role, String permission) { | ||||
|   bool checkRole(String role, String permission) { | ||||
|  | ||||
|     if (!_connected) { | ||||
|       return false; | ||||
| @@ -750,17 +757,17 @@ class InvenTreeAPI { | ||||
|  | ||||
|     // If we do not have enough information, assume permission is allowed | ||||
|     if (roles.isEmpty) { | ||||
|       debug("checkPermission - no roles defined!"); | ||||
|       debug("checkRole - no roles defined!"); | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     if (!roles.containsKey(role)) { | ||||
|       debug("checkPermission - role '$role' not found!"); | ||||
|       debug("checkRole - role '$role' not found!"); | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     if (roles[role] == null) { | ||||
|       debug("checkPermission - role '$role' is null!"); | ||||
|       debug("checkRole - role '$role' is null!"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| @@ -773,7 +780,7 @@ class InvenTreeAPI { | ||||
|       } else { | ||||
|         // Unknown error - report it! | ||||
|         sentryReportError( | ||||
|           "api.checkPermission", | ||||
|           "api.checkRole", | ||||
|           error, stackTrace, | ||||
|           context: { | ||||
|             "role": role, | ||||
| @@ -788,6 +795,54 @@ class InvenTreeAPI { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Check if the user has the particular model permission assigned | ||||
|    * e.g. "company", "add" | ||||
|    */ | ||||
|   bool checkPermission(String model, String permission) { | ||||
|     if (!_connected) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (permissions.isEmpty) { | ||||
|       // Not enough information available - default to True | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     if (!permissions.containsKey(model)) { | ||||
|       debug("checkPermission - model '$model' not found!"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (permissions[model] == null) { | ||||
|       debug("checkPermission - model '$model' is null!"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       List<String> perms = List.from(permissions[model] as List<dynamic>); | ||||
|       return perms.contains(permission); | ||||
|     } catch (error, stackTrace) { | ||||
|       if (error is TypeError) { | ||||
|         // Ignore TypeError | ||||
|       } else { | ||||
|         // Unknown error - report it! | ||||
|         sentryReportError( | ||||
|             "api.checkPermission", | ||||
|             error, stackTrace, | ||||
|             context: { | ||||
|               "model": model, | ||||
|               "permission": permission, | ||||
|               "error": error.toString(), | ||||
|             } | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       // Unable to determine permission - assume true? | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   // Perform a PATCH request | ||||
|   Future<APIResponse> patch(String url, {Map<String, dynamic> body = const {}, int? expectedStatusCode}) async { | ||||
|   | ||||
| @@ -212,7 +212,7 @@ class InvenTreeModel { | ||||
|   // Test if the user can "edit" this model | ||||
|   bool get canEdit { | ||||
|     for (String role in rolesRequired) { | ||||
|       if (InvenTreeAPI().checkPermission(role, "change")) { | ||||
|       if (InvenTreeAPI().checkRole(role, "change")) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
| @@ -224,7 +224,7 @@ class InvenTreeModel { | ||||
|   // Test if the user can "create" this model | ||||
|   bool get canCreate { | ||||
|     for (String role in rolesRequired) { | ||||
|       if (InvenTreeAPI().checkPermission(role, "add")) { | ||||
|       if (InvenTreeAPI().checkRole(role, "add")) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
| @@ -236,7 +236,7 @@ class InvenTreeModel { | ||||
|   // Test if the user can "delete" this model | ||||
|   bool get canDelete { | ||||
|     for (String role in rolesRequired) { | ||||
|       if (InvenTreeAPI().checkPermission(role, "delete")) { | ||||
|       if (InvenTreeAPI().checkRole(role, "delete")) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
| @@ -248,7 +248,7 @@ class InvenTreeModel { | ||||
|   // Test if the user can "view" this model | ||||
|   bool get canView { | ||||
|     for (String role in rolesRequired) { | ||||
|       if (InvenTreeAPI().checkPermission(role, "view")) { | ||||
|       if (InvenTreeAPI().checkRole(role, "view")) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -234,6 +234,9 @@ | ||||
|   "company": "Company", | ||||
|   "@company": {}, | ||||
|  | ||||
|   "companyAdd": "Add Company", | ||||
|   "@companyAdd": {}, | ||||
|  | ||||
|   "companyEdit": "Edit Company", | ||||
|   "@companyEdit": {}, | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
|  | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter_speed_dial/flutter_speed_dial.dart"; | ||||
| import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; | ||||
|  | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| @@ -35,6 +37,48 @@ class _CompanyListWidgetState extends RefreshableState<CompanyListWidget> { | ||||
|   @override | ||||
|   String getAppBarTitle() => widget.title; | ||||
|  | ||||
|   Future<void> _addCompany(BuildContext context) async { | ||||
|  | ||||
|     InvenTreeCompany().createForm( | ||||
|       context, | ||||
|       L10().companyAdd, | ||||
|       data: widget.filters, | ||||
|       onSuccess: (result) async { | ||||
|         Map<String, dynamic> data = result as Map<String, dynamic>; | ||||
|  | ||||
|         if (data.containsKey("pk")) { | ||||
|           var company = InvenTreeCompany.fromJson(data); | ||||
|  | ||||
|           Navigator.push( | ||||
|             context, | ||||
|             MaterialPageRoute( | ||||
|               builder: (context) => CompanyDetailWidget(company) | ||||
|             ) | ||||
|           ); | ||||
|         } | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   List<SpeedDialChild> actionButtons(BuildContext context) { | ||||
|     List<SpeedDialChild> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission("company", "add")) { | ||||
|       actions.add( | ||||
|           SpeedDialChild( | ||||
|               child: Icon(TablerIcons.circle_plus, color: Colors.green), | ||||
|               label: L10().companyAdd, | ||||
|               onTap: () { | ||||
|                 _addCompany(context); | ||||
|               } | ||||
|           ) | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return actions; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget getBody(BuildContext context) { | ||||
|     return PaginatedCompanyList(widget.title, widget.filters); | ||||
|   | ||||
| @@ -183,7 +183,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> with BaseWidgetPr | ||||
|     bool allowed = true; | ||||
|  | ||||
|     if (role.isNotEmpty || permission.isNotEmpty) { | ||||
|       allowed = InvenTreeAPI().checkPermission(role, permission); | ||||
|       allowed = InvenTreeAPI().checkRole(role, permission); | ||||
|     } | ||||
|  | ||||
|     return GestureDetector( | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| name: inventree | ||||
| description: InvenTree stock management | ||||
|  | ||||
| version: 0.17.4+96 | ||||
| version: 0.18.0+97 | ||||
|  | ||||
| environment: | ||||
|   sdk: ">=2.19.5 <3.13.0" | ||||
|   | ||||
| @@ -117,10 +117,10 @@ void main() { | ||||
|       assert(api.roles.isNotEmpty); | ||||
|  | ||||
|       // Check available permissions | ||||
|       assert(api.checkPermission("part", "change")); | ||||
|       assert(api.checkPermission("stock_location", "delete")); | ||||
|       assert(!api.checkPermission("part", "weirdpermission")); | ||||
|       assert(api.checkPermission("blah", "bloo")); | ||||
|       assert(api.checkRole("part", "change")); | ||||
|       assert(api.checkRole("stock_location", "delete")); | ||||
|       assert(!api.checkRole("part", "weirdpermission")); | ||||
|       assert(api.checkRole("blah", "bloo")); | ||||
|  | ||||
|       debugContains("Received token from server"); | ||||
|       debugContains("showSnackIcon: 'Connected to Server'"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user