mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-11-04 07:15:46 +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
 | 
					### 0.17.4 - January 2025
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
- Display responsible owner for orders
 | 
					- Display responsible owner for orders
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										79
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								lib/api.dart
									
									
									
									
									
								
							@@ -237,9 +237,12 @@ class InvenTreeAPI {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  UserProfile? profile;
 | 
					  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 = {};
 | 
					  Map<String, dynamic> roles = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Available user permissions are loaded when connecting to the server
 | 
				
			||||||
 | 
					  Map<String, dynamic> permissions = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Profile authentication token
 | 
					  // Profile authentication token
 | 
				
			||||||
  String get token => profile?.token ?? "";
 | 
					  String get token => profile?.token ?? "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -701,12 +704,11 @@ class InvenTreeAPI {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var data = response.asMap();
 | 
					    var data = response.asMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (data.containsKey("roles")) {
 | 
					    if (!data.containsKey("roles")) {
 | 
				
			||||||
      // Save a local copy of the user roles
 | 
					
 | 
				
			||||||
      roles = (response.data["roles"] ?? {}) as Map<String, dynamic>;
 | 
					      roles = {};
 | 
				
			||||||
 | 
					      permissions = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      showServerError(
 | 
					      showServerError(
 | 
				
			||||||
        apiUrl,
 | 
					        apiUrl,
 | 
				
			||||||
        L10().serverError,
 | 
					        L10().serverError,
 | 
				
			||||||
@@ -714,6 +716,11 @@ class InvenTreeAPI {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    roles = (data["roles"] ?? {}) as Map<String, dynamic>;
 | 
				
			||||||
 | 
					    permissions = (data["permissions"] ?? {}) as Map<String, dynamic>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Request plugin information from the server
 | 
					  // Request plugin information from the server
 | 
				
			||||||
@@ -740,9 +747,9 @@ class InvenTreeAPI {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Check if the user has the given role.permission assigned
 | 
					   * 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) {
 | 
					    if (!_connected) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
@@ -750,17 +757,17 @@ class InvenTreeAPI {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // If we do not have enough information, assume permission is allowed
 | 
					    // If we do not have enough information, assume permission is allowed
 | 
				
			||||||
    if (roles.isEmpty) {
 | 
					    if (roles.isEmpty) {
 | 
				
			||||||
      debug("checkPermission - no roles defined!");
 | 
					      debug("checkRole - no roles defined!");
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!roles.containsKey(role)) {
 | 
					    if (!roles.containsKey(role)) {
 | 
				
			||||||
      debug("checkPermission - role '$role' not found!");
 | 
					      debug("checkRole - role '$role' not found!");
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (roles[role] == null) {
 | 
					    if (roles[role] == null) {
 | 
				
			||||||
      debug("checkPermission - role '$role' is null!");
 | 
					      debug("checkRole - role '$role' is null!");
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -773,7 +780,7 @@ class InvenTreeAPI {
 | 
				
			|||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // Unknown error - report it!
 | 
					        // Unknown error - report it!
 | 
				
			||||||
        sentryReportError(
 | 
					        sentryReportError(
 | 
				
			||||||
          "api.checkPermission",
 | 
					          "api.checkRole",
 | 
				
			||||||
          error, stackTrace,
 | 
					          error, stackTrace,
 | 
				
			||||||
          context: {
 | 
					          context: {
 | 
				
			||||||
            "role": role,
 | 
					            "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
 | 
					  // Perform a PATCH request
 | 
				
			||||||
  Future<APIResponse> patch(String url, {Map<String, dynamic> body = const {}, int? expectedStatusCode}) async {
 | 
					  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
 | 
					  // Test if the user can "edit" this model
 | 
				
			||||||
  bool get canEdit {
 | 
					  bool get canEdit {
 | 
				
			||||||
    for (String role in rolesRequired) {
 | 
					    for (String role in rolesRequired) {
 | 
				
			||||||
      if (InvenTreeAPI().checkPermission(role, "change")) {
 | 
					      if (InvenTreeAPI().checkRole(role, "change")) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -224,7 +224,7 @@ class InvenTreeModel {
 | 
				
			|||||||
  // Test if the user can "create" this model
 | 
					  // Test if the user can "create" this model
 | 
				
			||||||
  bool get canCreate {
 | 
					  bool get canCreate {
 | 
				
			||||||
    for (String role in rolesRequired) {
 | 
					    for (String role in rolesRequired) {
 | 
				
			||||||
      if (InvenTreeAPI().checkPermission(role, "add")) {
 | 
					      if (InvenTreeAPI().checkRole(role, "add")) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -236,7 +236,7 @@ class InvenTreeModel {
 | 
				
			|||||||
  // Test if the user can "delete" this model
 | 
					  // Test if the user can "delete" this model
 | 
				
			||||||
  bool get canDelete {
 | 
					  bool get canDelete {
 | 
				
			||||||
    for (String role in rolesRequired) {
 | 
					    for (String role in rolesRequired) {
 | 
				
			||||||
      if (InvenTreeAPI().checkPermission(role, "delete")) {
 | 
					      if (InvenTreeAPI().checkRole(role, "delete")) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -248,7 +248,7 @@ class InvenTreeModel {
 | 
				
			|||||||
  // Test if the user can "view" this model
 | 
					  // Test if the user can "view" this model
 | 
				
			||||||
  bool get canView {
 | 
					  bool get canView {
 | 
				
			||||||
    for (String role in rolesRequired) {
 | 
					    for (String role in rolesRequired) {
 | 
				
			||||||
      if (InvenTreeAPI().checkPermission(role, "view")) {
 | 
					      if (InvenTreeAPI().checkRole(role, "view")) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -234,6 +234,9 @@
 | 
				
			|||||||
  "company": "Company",
 | 
					  "company": "Company",
 | 
				
			||||||
  "@company": {},
 | 
					  "@company": {},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "companyAdd": "Add Company",
 | 
				
			||||||
 | 
					  "@companyAdd": {},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  "companyEdit": "Edit Company",
 | 
					  "companyEdit": "Edit Company",
 | 
				
			||||||
  "@companyEdit": {},
 | 
					  "@companyEdit": {},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "package:flutter/material.dart";
 | 
					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/api.dart";
 | 
				
			||||||
import "package:inventree/l10.dart";
 | 
					import "package:inventree/l10.dart";
 | 
				
			||||||
@@ -35,6 +37,48 @@ class _CompanyListWidgetState extends RefreshableState<CompanyListWidget> {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  String getAppBarTitle() => widget.title;
 | 
					  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
 | 
					  @override
 | 
				
			||||||
  Widget getBody(BuildContext context) {
 | 
					  Widget getBody(BuildContext context) {
 | 
				
			||||||
    return PaginatedCompanyList(widget.title, widget.filters);
 | 
					    return PaginatedCompanyList(widget.title, widget.filters);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -183,7 +183,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> with BaseWidgetPr
 | 
				
			|||||||
    bool allowed = true;
 | 
					    bool allowed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (role.isNotEmpty || permission.isNotEmpty) {
 | 
					    if (role.isNotEmpty || permission.isNotEmpty) {
 | 
				
			||||||
      allowed = InvenTreeAPI().checkPermission(role, permission);
 | 
					      allowed = InvenTreeAPI().checkRole(role, permission);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return GestureDetector(
 | 
					    return GestureDetector(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
name: inventree
 | 
					name: inventree
 | 
				
			||||||
description: InvenTree stock management
 | 
					description: InvenTree stock management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version: 0.17.4+96
 | 
					version: 0.18.0+97
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=2.19.5 <3.13.0"
 | 
					  sdk: ">=2.19.5 <3.13.0"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,10 +117,10 @@ void main() {
 | 
				
			|||||||
      assert(api.roles.isNotEmpty);
 | 
					      assert(api.roles.isNotEmpty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Check available permissions
 | 
					      // Check available permissions
 | 
				
			||||||
      assert(api.checkPermission("part", "change"));
 | 
					      assert(api.checkRole("part", "change"));
 | 
				
			||||||
      assert(api.checkPermission("stock_location", "delete"));
 | 
					      assert(api.checkRole("stock_location", "delete"));
 | 
				
			||||||
      assert(!api.checkPermission("part", "weirdpermission"));
 | 
					      assert(!api.checkRole("part", "weirdpermission"));
 | 
				
			||||||
      assert(api.checkPermission("blah", "bloo"));
 | 
					      assert(api.checkRole("blah", "bloo"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      debugContains("Received token from server");
 | 
					      debugContains("Received token from server");
 | 
				
			||||||
      debugContains("showSnackIcon: 'Connected to Server'");
 | 
					      debugContains("showSnackIcon: 'Connected to Server'");
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user