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
 | 
			
		||||
---
 | 
			
		||||
- 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