ShoppingCartOrder Check Customization

We have identified that products can only be checked in the shopping cart if they are standard products with AccProduct.

If we want to check multi-request resources (QERReuse), such as for duplicate checks or compliance checks, we cannot use the standard libraries of One Identity because the logic is embedded deeply within the Customizer DLL.

Currently, we have a script library that we can call as a customization in the shop, but we are unable to make any changes to it.

Our goal is to provide an alternative item to be checked instead of objectkeyorderd, as objectkeyorderd and AccProduct are always the same.

The code we have so far looks like this:

#If Not SCRIPTDEBUGGER Then
References NLog.Dll
#End If

''' <summary>
''' _CCC_ShoppingCartOrder_Check
''' </summary>
''' <param name="UID_ShoppingCartOrder"></param>
''' <param name="configJson"></param>
''' <returns></returns>
Public Function _CCC_ShoppingCartOrder_Check(ByVal UID_ShoppingCartOrder As String, ByVal configJson As String) As String

	' Variablen
	Dim counterror As Integer = 0
	Dim countwarning As Integer = 0
	Dim culLang As System.Globalization.CultureInfo = New System.Globalization.CultureInfo("de-DE")
	VI.Base.LanguageManager.SetSystemCulture(culLang)
	Dim log As NLog.LogSession = New NLog.LogSession(NameOf(_CCC_ShoppingCartOrder_Check),"")
	
	' Erste Variante mit Submit
	Dim check = New QER.CompositionApi.ITShop.ShoppingCartSubmit(UID_ShoppingCartOrder)
	Dim ConfigJsonParm As String = check.GetConfigJson
	
	check.Check.Config.CheckMode = QER.CompositionApi.ITShop.CheckMode.CheckOnly
	Dim tCartItemCheckResult As QER.CompositionApi.ITShop.CartItemCheckResult
	
	log.Info("Shopping Cart: " & UID_ShoppingCartOrder & " will be checked...")
	
	Dim checkResult = check.CheckAsync(Session).Result
	
	log.Info("Check Config: ")
	log.Info(ConfigJsonParm )
	
	' Für alle Bestellpositionen
	
	Dim items = checkResult.Items()
	For Each tCartItemCheckResult In items
		
		' Bestellpositionen Prüfungen durchführen
		
		log.Info("  > Cart Item " & tCartItemCheckResult.ToString & " check result...")
		Dim itemsChecks = tCartItemCheckResult.checks()

		' Für alle gefundenen Prüfungsresultate
		
		For Each checks In itemsChecks
			
			' Resulatat ausgeben
			
			log.Info("    > ID : " + checks.id + ", Status :" + checks.Status.toString + ", Title :" + checks.title)
			
			Select Case checks.Status.toString
			    Case "Warning"
					countwarning += 1
			    Case "Error"
					counterror += 1
			    Case Else
			End Select
			
		Next
	Next

	Return " In " & CStr(items.count) & " Cart Items, there are " & CStr(countwarning) & " warnings and " & CStr(counterror) & " errors."

End Function

Any help would be appreciated!

Top Replies

Parents
  • Hello,

    Requests for multi-request resources (QERReuse) go through the shopping cart validation just like all other products, even though it is true that, by definition, some checks will always pass for these requests.

    That being said, I don't understand what problem you are trying to solve. Are you looking to add custom validation logic to the shopping cart?

Reply
  • Hello,

    Requests for multi-request resources (QERReuse) go through the shopping cart validation just like all other products, even though it is true that, by definition, some checks will always pass for these requests.

    That being said, I don't understand what problem you are trying to solve. Are you looking to add custom validation logic to the shopping cart?

Children
  • Hello,

    I have also found in my tests that I get a positive test result in all points for the multi-request resources (QERReuse).
    The problem is, if the ordered subject is not in the objectkeyordered column in QERReuse, how can the the system check for duplicate orders in the shopping cart?
    The system needs to know in which custom-defined column the actually ordered subject is defined.

    Example:

    If I create a multi-orderable product with which certain resources can be ordered, such as (resource1, resource2, etc.), then you can order several resouces and you can also have a column with which you can select this resource, for example, CCC_Resource with a FK.

    However, the system does not know that if I have selected resource A, I can order at the same time (Shopping Cart) also resource B, C, and D, etc., but not A again. I cannot define anywhere that for this multi-orderable product, the CCC_Resource column contains the subject instead of objectkeyordered.

    Additionally, I cannot create compliance rules where I define that managers are allowed to order Resource C, where in the other hand regular employees can only do so with an additional exception approver.
    You can also see that when creating a compliance rule for entitlements, you see the QERResource but not the other multi-orderable tables. Even with SQL, you don’t have the flexibility needed there in the Compliance Rules.

    All these checks are reported as successful, but I think they are not checked, but rather ignored.

    I have already opened a service request 02433533, but I suspect they did not understand what I want exactly. I do not expect it to be possible in the standard, but only that as a customer, I can perform duplicate checks and compliance checks on QERReuse with additional check scripts and API without having to reprogram the entire logic. From my point of view, part of the check code, which is in the customizer DDL, should be accessible to the customer.
    For the QERReuseUS it is even more important, that somebody cannot order something that he already has ordered.

  • Hello,

    Thanks for elaborating, but I'm afraid I now have more questions ;-)

    > If I create a multi-orderable product with which certain resources can be ordered

    What is the relation between the QERReuse and these other resources?

    > You can also see that when creating a compliance rule for entitlements, you see the QERResource but not the other multi-orderable tables.

    That is because objects of type QERReuse, QERAssign and QERReuseUS are never actually assigned to the recipient! This is why you can't use them to build compliance rules.

    Furthermore, QERReuse/QERReuseUS are multi-requestable resource types that you can request as many times as desired. That means that you cannot have duplicate requests so the checking logic for duplicate requests skips these types.

    That being said, it is possible to add custom check logic in the shopping cart. However, it sounds like you will not be able to re-use any of the default compliance logic.

  • That being said, it is possible to add custom check logic in the shopping cart. However, it sounds like you will not be able to re-use any of the default compliance logic.

    Can you point to the relevant function? I got a product with Request Parameters which need to be unique (no request of this product may have same parameter value as another request). I currently have a Calculated Decision which denies the request in case of duplicate values, but it seems way smarter (and more userfriendly) to inform the user prior submitting instead of automatically rejecting the request.

  • What is the relation between the QERReuse and these other resources?

    QERReuse and QERReuseUS are products that can be ordered multiple times. The issue is that it is currently possible to order them multiple times without any duplication check at the product level (Sho Product). However, within these multiple-time orderable products, there is a specific column (or a property in the new enhanced properties at pwo) that contains the item being ordered. The duplicate check in the shopping cart needs to be performed on this specific property or column.

    Example: If I have a product that can be ordered multiple times, such as “ownership change of a specific entitlement,” it can appear multiple times in the shopping cart, but not for the same entitlement. This is not possible today if you have a custom column with the subject that is ordered.



  • Your example is almost what we do (although we do not use a customn column in terms of a schema extension).

    In a simplified way: Let's say that we want to provide a product with a bunch of variants (like you have on Amazon: On the iPhone product page, you can select the color and memory size). Instead of creating an ITShop product for each variant, we use one product only and get the variant by a request parameter. Best Practise so far, agreed?

    The requirement would be: A person may request multiple iPhones, but not a variant he already has. (please ignore the real-live implications of that, it's just a simplified example)

    Currently, we have an Approval-Workflow with a CD where we evaluate the request and deny if an identical variant is already assigned. Hence, I would like to extend to checks performed in Shopping-Cart to tell the user beforehand. So my question comes down to:

    How can I edit/extend the rules which are applied when clicking the "Check Shopping Cart"?

  • Hi,

    To add new checks to the IT shop, you can extend the Composition API with a plugin DLL. This process is very similar to adding an API server plugin, with some differences:

    - It must be a separate DLL, it cannot be an API Server plugin.

    - The DLL name must match the pattern  *.CompositionApi.dll.

    - Add assembly references to QER.CompositionApi.dll and QBM.CompositionApi.dll.

    - You should deploy this DLL to all API servers and job servers. This is because the check results are stored as JSON and deserialized, and that fails if your custom check type cannot be found.

    The basic process is also described here:
    https://github.com/OneIdentity/IdentityManager.ApiSdk/blob/v93/doc/05-composition-api-plugins.md#shopping-cart-checks

    However, the code on that page is for the upcoming 9.3 release, and the interfaces have slightly changed. I've made the changes for 9.2 in the code here. Obviously, there is a placeholder where the check logic should go, so you can insert any checking logic.

        public class CartCheckProvider : ICartCheckProvider, IKnownTypeProvider
        {
    
            public IEnumerable<Type> GetTypes()
            {
                return new[] { typeof(SampleCheck) };
            }
    
            public ICartCheck GetCartCheck(ICartItemCheckContext context)
            {
                return new SampleCartCheck(context);
            }
        }
    
        public class SampleCartCheck : ICartCheck
        {
            private readonly ICartItemCheckContext _context;
            private SampleCheck _check;
    
            public SampleCartCheck(ICartItemCheckContext context)
            {
                _context = context;
            }
    
            public IReadOnlyList<ICartItemCheck> GetItemChecks()
            {
                _check = new SampleCheck(_context);
                return new[] { _check };
            }
    
            public Task CheckAsync(CancellationToken ct = default)
            {
                return _check.ProcessAsync(ct);
            }
        }
    
        public class SampleCheck : ICartItemCheck
        {
            private readonly ICartItemCheckContext _context;
    
            public SampleCheck(ICartItemCheckContext context)
            {
                _context = context;
            }
    
            internal async Task ProcessAsync(CancellationToken ct = default)
            {
                var session = _context.Session;
                var cartitem = _context.Item;
                // Any logic required to calculate the check result should go here.
                // At the end we will have a result:
                Status = CheckStatus.Success; // ... or CheckStatus.Error
                                              // Set the description text to provide more information about the result.
                if (Status == CheckStatus.Success)
                {
                    ResultText = "This check was successful";
                }
                else
                {
                    ResultText = "This check failed";
                }
            }
    
            public string Id => "SampleCartItemCheck";
            public CheckStatus Status { get; set; } = CheckStatus.Pending;
            public string Title => "Sample customizable check";
            public string ResultText { get; set; }
            // Populate this property to append any serializable data to the result.
            public object Detail => null;
        }

  • I will have a deeper look into this. Actually I was hoping that these checks would be configurable using some rules, e.g. like in Identity Audit.

    Thanks Hanno, appreciate pointing out the differences between 9.2 and 9.3 Slight smile

  • Hi Hanno, thanks, We will try to implement this solution approach. Regards René