Uploaded image for project: 'Kuali Rice Development'
  1. Kuali Rice Development
  2. KULRICE-8610

Make it so that the role qualifiers built in the DocumentTypePermissionService can be configurable by client apps.

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: 2.1.3
    • Fix Version/s: 2.1.3
    • Component/s: Development
    • Security Level: Public (Public: Anyone can view)
    • Labels:
      None
    • Rice Module:
      KNS
    • Application Requirement:
      KC
    • KAI Review Status:
      Not Required
    • KTI Review Status:
      Not Required

      Description

      This relates to KULRICE-8490. In that jira, we addressed the issue by adding the same kind of parameter check that is used in the canRoute and canSave methods. This works in KC but only because it bypasses all KIM permissions checks. The ideal situation would be where we can configure these from the KC end either by overriding some methods in the service or by spring injection. The details of the implementation can be discussed further.

        Attachments

          Issue Links

            Activity

            Hide
            gathreya Gayathri Athreya added a comment -

            Claus, I assigned it to you because we discussed this and you worked on KULRICE-8490. If it needs to go through the DM, that is obviously fine as well.

            Show
            gathreya Gayathri Athreya added a comment - Claus, I assigned it to you because we discussed this and you worked on KULRICE-8490 . If it needs to go through the DM, that is obviously fine as well.
            Hide
            gathreya Gayathri Athreya added a comment - - edited

            It was determined that the current solution of checking the useKimPermission parameter does not work for KC

            public boolean canRecall(String principalId, String documentId, DocumentType documentType, List<String> routeNodeNames, String documentStatus, String appDocStatus, String initiatorPrincipalId) {
                    validatePrincipalId(principalId);
                    validateDocumentType(documentType);
                    validateRouteNodeNames(routeNodeNames);
                    validateDocumentStatus(documentStatus);
                    // no need to validate appdocstatus, this is a free-form application defined value
            
                    // add appDocStatus to the details
                    List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetails(documentType, routeNodeNames, documentStatus);
                    if (!StringUtils.isBlank(appDocStatus)) {
                        for (Map<String, String> details: permissionDetailList) {
                            details.put(KewApiConstants.APP_DOC_STATUS_DETAIL, appDocStatus);
                        }
                    }
            
                    boolean foundAtLeastOnePermission = false;
                    boolean authorizedByPermission = false;
                    boolean principalIsInitiator = StringUtils.equals(initiatorPrincipalId, principalId);
            
                    // loop over permission details, only one of them needs to be authorized
                    for (Map<String, String> permissionDetails : permissionDetailList) {
                        Map<String, String> roleQualifiers = buildDocumentIdRoleDocumentTypeDocumentStatusQualifiers(documentType, documentStatus, documentId, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL));
                        if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails)) {
                            if (getPermissionService().isPermissionDefinedByTemplate(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails)) {
                                foundAtLeastOnePermission = true;
                                if (getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
                                        KewApiConstants.RECALL_PERMISSION, permissionDetails, roleQualifiers)) {
                                    authorizedByPermission = true;
                                    break;
                                }
                            }
                        }
                    }
            
                    // alternative could be to only authorize initiator if the permission is omitted
                    // (i.e. exclude initiator if the initiator does not have the recall permission)
                    return authorizedByPermission;
                }
            

            The above useKimPermissions check was added to bypass KIM authorization but turns out it will never return true for us because of the following:
            authorizedByPermission is set to false initially and when the useKimPermission is false (it is false in KC because we set the KIM_PRIORITY_ON_DOC_TYP_PERMS_IND parameter to N), it never gets set to true which means it is always going to return false for us.
            Also, using a document policy of InitiatorCanRecall will also not work because the document can be recalled by non-initiators.

            Show
            gathreya Gayathri Athreya added a comment - - edited It was determined that the current solution of checking the useKimPermission parameter does not work for KC public boolean canRecall( String principalId, String documentId, DocumentType documentType, List< String > routeNodeNames, String documentStatus, String appDocStatus, String initiatorPrincipalId) { validatePrincipalId(principalId); validateDocumentType(documentType); validateRouteNodeNames(routeNodeNames); validateDocumentStatus(documentStatus); // no need to validate appdocstatus, this is a free-form application defined value // add appDocStatus to the details List<Map< String , String >> permissionDetailList = buildDocumentTypePermissionDetails(documentType, routeNodeNames, documentStatus); if (!StringUtils.isBlank(appDocStatus)) { for (Map< String , String > details: permissionDetailList) { details.put(KewApiConstants.APP_DOC_STATUS_DETAIL, appDocStatus); } } boolean foundAtLeastOnePermission = false ; boolean authorizedByPermission = false ; boolean principalIsInitiator = StringUtils.equals(initiatorPrincipalId, principalId); // loop over permission details, only one of them needs to be authorized for (Map< String , String > permissionDetails : permissionDetailList) { Map< String , String > roleQualifiers = buildDocumentIdRoleDocumentTypeDocumentStatusQualifiers(documentType, documentStatus, documentId, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL)); if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails)) { if (getPermissionService().isPermissionDefinedByTemplate(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails)) { foundAtLeastOnePermission = true ; if (getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails, roleQualifiers)) { authorizedByPermission = true ; break ; } } } } // alternative could be to only authorize initiator if the permission is omitted // (i.e. exclude initiator if the initiator does not have the recall permission) return authorizedByPermission; } The above useKimPermissions check was added to bypass KIM authorization but turns out it will never return true for us because of the following: authorizedByPermission is set to false initially and when the useKimPermission is false (it is false in KC because we set the KIM_PRIORITY_ON_DOC_TYP_PERMS_IND parameter to N), it never gets set to true which means it is always going to return false for us. Also, using a document policy of InitiatorCanRecall will also not work because the document can be recalled by non-initiators.
            Hide
            ahamid Aaron Hamid (Inactive) added a comment -

            work has been completed and ready to commit once database change goes in.

            however, after reviewing the KNS/KRAD DocumentAuthorizer I'm wondering if anybody can comment on the relationship of that mechanism to this new one. there seems to be quite an overlap. the KNS/KRAD DocumentAuthorizer framework provides for custom details and qualifiers via getPermissionDetailValues and getRoleQualification, and mostly performs direct KIM permission checks itself. should one delegate to the other?

            Show
            ahamid Aaron Hamid (Inactive) added a comment - work has been completed and ready to commit once database change goes in. however, after reviewing the KNS/KRAD DocumentAuthorizer I'm wondering if anybody can comment on the relationship of that mechanism to this new one. there seems to be quite an overlap. the KNS/KRAD DocumentAuthorizer framework provides for custom details and qualifiers via getPermissionDetailValues and getRoleQualification , and mostly performs direct KIM permission checks itself. should one delegate to the other?
            Hide
            gathreya Gayathri Athreya added a comment -

            This worked smoothly for us. Thanks a lot Aaron

            Show
            gathreya Gayathri Athreya added a comment - This worked smoothly for us. Thanks a lot Aaron

              People

              • Assignee:
                ahamid Aaron Hamid (Inactive)
                Reporter:
                gathreya Gayathri Athreya
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 2 days, 1 hour
                  2d 1h