Trying to read queries from a folder programmatically

I'm in the process of building an AJAX-y search for edit field in a larger form.  The lookup needs to use IQA queries from a particular folder (configured property of my iPart).

I'm hitting a snag in the following part of the code.  (code includes "using Asi.Business.Common")   The error I'm getting (exception I'm catching) suggests I don't have permission to that folder, but the error message was in the sample code, so I'm not sure that's the real problem.

What am I missing to be able to do this?  Or where should I be looking to find the problem?

string IQAFolder = "$/ContactManagement/DefaultSystem/Queries/Contacts";
Document document = DocumentController.Document(IQAFolder);
if (document.DocumentTypeCode.ToString() == "FOL")
{
    Document[] queries = DocumentController.DocumentsInFolder(IQAFolder);
    foreach (Document doc in queries)
    {
        RadComboBoxItem temp = new RadComboBoxItem();
        temp.Text = doc.Description;
        temp.Value = doc.DocumentVersionKey.ToString();
        cbo.Items.Add(temp);
    }
}

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Is the code running in a

Is the code running in a context where it [or the user making the request] has already authenticated? If you're running inside the iMIS application (appserver, WCM server, public server, whatever) then it should already be.

Otherwise (or if GUEST doesn't have read access to the folder) you may need to authenticate yourself. Just add a using(Asi.Security.SecurityContext.ImpersonateAnonymous()) { ... } around your code. If GUEST doesn't have access, you can either a) force them to log in first, b) adjust the permissions on the folder [and all containing folders], or c) use Impersonate("MANAGER") instead, although this latter is not the recommended solution.

Also, the actual error message/stack trace would be more descriptive. ;)

Eric Means
System Architect, ASI

 You can't access business

 You can't access business objects by using anonymous security context.

I have written some code which gets all list of IQAs based on the logged in user and this procedure also includes some other coditions may be you can ignore those options

 

 using (Asi.Security.SecurityContext.Impersonate(Asi.AppContext.CurrentIdentity.LoginName))
                    {
                        IList<Guid> IQAs = Asi.Business.Common.DocumentSystem.DocumentDescendantKeys(
                                     Asi.Business.Common.DocumentSystem.DocumentHierarchyRootKey, true,
                                     Asi.Business.Common.DocumentKeyReturnType.DocumentKey);
                        string[] roles = Asi.Security.AppPrincipal.CurrentPrincipal.Roles;
 
                        ArrayList ArrayIQADocs = new ArrayList();
                        Hashtable htIQAs = new Hashtable();
                        foreach (Guid guid in IQAs)
                        {
 
                            bool AddDoc = false;
                            Document doc = DocumentController.GetLatestVersion(guid);
 
                            if (!doc.IsSystem && doc.DocumentTypeCode == "IQD")
                            {
                                AccessItem[] accItems = doc.AccessSet.AccessItems;
                                foreach (AccessItem ac in accItems)
                                {
                                    if (Asi.AppContext.CurrentPrincipal.IsInRole(ac.Role.Name))
                                        if (ac.Role.Name != "Everyone" && ac.Role.Name != "SysAdmin")
                                            AddDoc = true;
                                }
                            }
                            if (AddDoc)
                            {
                                if (!htIQAs.ContainsKey(doc.Path))
                                {
                                    htIQAs.Add(doc.Path, doc.Path);
                                    ArrayIQADocs.Add(doc);
                                }
                            }
 
                        }
                        IQADocs = (Document[])ArrayIQADocs.ToArray(typeof(Document));
                        Context.Session[docSessionKey] = IQADocs;
                    }

 

 

You can't access business

"You can't access business objects by using anonymous security context."

You absolutely can (assuming you mean using ImpersonateAnonymous); there is code in the shipping iMIS application server that does so. However, in order to do so, if the business object is a secured type (has an AccessKey column in its BO definition) then the GUEST user must have access to anything you want it to load (including containing folders, for objects in the document system).

You should not need to impersonate the currently-logged-in user; if you are having to do so, something is off. We set the current thread's principal (which is what IQA and BOD use to determine the current security context) at the start of each request specifically so that kind of code is not required.

Eric Means
System Architect, ASI

Hi Eric, Thanks for the tip. I

Hi Eric,

Thanks for the tip. I tried using ImpersonateAnonymous access before accessing IQA and BOD objects, But it didn't fetch any results then I used impersonate method I got my results as expected

Is it something to do with this below configuration from web.config.

<add key="Authenticate.Anonymous.Allow" value="false" />

Thanks

As far as I know that

As far as I know that setting is obsolete and doesn't actually do anything.

You might check that the Authenticate.Anonymous.UserId value is set to GUEST.

Eric Means
System Architect, ASI

Running in context

Yes, the code is part of an iPart running in the Casual view, and the user is authenticated.

The folder has Everyone Full Control.  The current user definitely has Read permissions to some queries in this folder, but not all.

At this point, I'm not getting an exception, just an empty result set.

--
Bruce Wilson
Director, Technical Services
RSM McGladrey, Inc.

Hm, looking at that code, it

Hm, looking at that code, it ends up using an OrganizationKey of Guid.Empty, which might be filtering out the folder you're looking for. The following is what we use when you drop a Lister2 in and tell it to use a folder of queries:

List<BusinessFilter> filters = new List<BusinessFilter>();
filters.Add(new BusinessFilter("ParentHierarchyKey", ComparisonType.Equal, folderHierarchyKey));
filters.Add(new BusinessFilter("DocumentTypeCode", ComparisonType.Equal, "IQD"));
DocumentHierarchyController controller =
DocumentHierarchyController.NewDocumentHierarchyController(BusinessContainer);
DataRow[] rows = controller.SelectWithFilter(filters.ToArray(), false, null, false, PublishedOnly);
if (rows.Length <= 0)
    rows = controller.SelectWithFilter(filters.ToArray(), true, null, true, PublishedOnly);

If that works, then the DocumentsInFolder behavior is probably buggy; it should try both Guid.Empty and the default organization key if one of them doesn't return a folder by that name.

Eric Means
System Architect, ASI

Must be OrganizationKey

I tried a different form of DocumentsInFolder that allowed me to provide OrganzationKey, and as a test I hard-coded it in.  That returned the expected results, so that must be the issue.

So the next logical question is: what is the best way to determine the default OrganizationKey?  Is it already in session or ViewState?

--
Bruce Wilson
Director, Technical Services
RSM McGladrey, Inc.

You can get it via a call to

You can get it via a call to OrganizationController.DefaultOrganization(BusinessContainer).OrganizationKey, or via AppPrincipal.CurrentPrincipal.AppIdentity.OrganizationKey. The latter won't hit the DB as far as I know; the former will on the first call.

Eric Means
System Architect, ASI

Thanks Eric

With the proper Org key and the information above, I was able to get the list I needed.  Thanks for the pointers.

--
Bruce Wilson
Director, Technical Services
RSM McGladrey, Inc.

Has this changed with

Has this changed with 15.1.3? I have an application that is running form the command line that is used to create security groups. With 15.1.2 it works perfectly well by using:

SecurityContext.LogonByUserId("MANAGER")

Though with 15.1.3 this nows throws a "Error loading: User" exception.
To work around this I have tried:

SecurityContext.ImpersonateAnonymous()

and

SecurityContext.Impersonate("MANAGER")

both of which appear to work, however in each case I end up with NULL query results as Bruce originally reported. I've checked the query and its path and they are set for everyone to have full control and we've tested the query actually works. Does anyone have any ideas, I'm stumped?

Thanks

Adam

No change in 15.1.3

I can't speak to your scenario, but I can tell you the iParts I created that use this functionality upgraded to 15.1.3 (after recompiling against the new Telerik controls) and worked without modification.
--
Bruce Wilson
Director, Technical Services
RSM McGladrey, Inc.

Resolved

I got to the bottom of it. There were a couple of things, first was an outdated asi.dll the application was using, looks like it got missed when the references were updated. The second issue was that the caching mechanism has changed with 15.1.3 so I needed to update the config and to use the caching.config of the iMIS app server. Moral of the story is check all the dll versions.

Thanks for the help

A