(Qlik Sense Server only, Qlik Sense Desktop has no Repository)
There are situations where you would like to know something from the system configuration (QMC) from inside of a load script, something like "Which custom attributes does my app have assigned?" Or "Which stream is the current app in?" I've seen the "bad" idea to connect to the Postgre repository database and read from the internal table structure. This internal structure may, and is likely to, change, so I would not build on this hack.
The correct way to do it is to use the QRS API (Qlik Repository Service). In theory, the QRS API operates on the https port 443 as well as on port 4242. If you used the latter, you have to present the public key of the server certificate, which cannot be done from the load script (remark added 2020: the REST Connector meanwhile allows to add a Certificate File and Key File, so you can setup a connection directly to port 4242 when allowed from a firewall point of view).
In order to use the port 443, you need to authenticate as a privileged user towards the server - your best bet from the script is to use the header authentication (pass the userid via http-header) and this requrires the setup of a Virtual Proxy on the server by a QMC admin.
Setup a new Virtual Proxy with Header Authentication
Use Postman or another tool to test the qrs endpoint response before going to the load script
Load Script: Use REST Connector with CONNECTION parameter
Step 1 - Setup Virtual Proxy
We want the script to be able to query the QRS api, so we have to give it a new "door" to authenicate. Set up a new Virtual Proxy like this: There will be a static pseudo user directory which we call "APIUSERS", whereas the user id itself will be provided in a http-header.
Dont forget to
add the Server node(s) under "Load balancing"
link this virtual proxy to a Proxy in the "Associated Items".
Note: We will have to come back to QMC/Users once again after making the first call using the header.
Step 2 - Test the qrs endpoint with header authentication
It is literally impossible to go straight to the REST connector from the script if you haven't tried the results from a tool that shows all response details (return code, possible error messages etc). My tool of choice is "Postman" (the app, not the Chrome-Plugin of the same name)
Lets use the server url + /header/ (this is the virtual proxy we created) + /qrs/about + &xrfkey= and a 16 digit combination, which you repeat in the http-headers under the key "X-Qlik-xrfkey" again. Also provide the userid as a 2nd http-header
You should get an answer like above in Json format. This means, you made it through the virtual proxy. A new user has been added to the QMC, namely the id "scriptload" (coming from the http-header) with the directory "APIUSERS" (coming from the virtual proxy setting).
Go back to the QMC and provide the new user the Role "AuditAdmin"
Now you can also query some details about the app. Try the following request, before we finally go to the Load Script. -.../qrs/app/full should provide all information about apps, including possible tags.
In order to get the details about one specific app you should use the "filter=" query-string, the syntax is like the Json object key, a comparison operator, and a constant. In my case: id eq <app-guid>
eq is "equals", don't use "=" which is a reserved character already used at "filter="
If this works fine, lets edit the app script.
3 - Create REST Connector call from Load Script
Go to the app's dataload editor and create a new connection of type "REST".
The principle I follow here is:
get over the initial dialog with hard-coded query-strings and http-headers to get the qrs call working (same Method as later, GET for GET, POST for POST)
load the data once
manipulate the created script with "WITH CONNECTION" argument and soft-code all the parameters to make it dynamic
Then load the data using the "Select Data" button in the Data connections list:
You can expand the Json response tree and deselect what you don't need. Be aware that each tree branch, which expands, will become a separate script table, so be conservative with what to load using a "need to know" judgement.
Insert the script. You will see the block called "RestConnectorMasterTable: SQL SELECT ..." and then several LOAD statements (in our case 4, one for the root and 3 childs which we selected above)
Until this point, the script is fully static. It only loads exactly this QRS endpoint and always load all apps.
Now lets bring some dynamics in. Find the last row of the first block where it reads FROM JSON (...) "root" PK "__KEY_root";
Before the semicolon insert (in a new line) WITH CONNECTION ()
With this parameter you can soft-code and overwrite any hard-coded entry from the "Edit Connection" dialog. If you omit a parameter in WITH CONNECTION, the original hard-coded entry from the Edit Connection dialog will be taken. You can also add more parameters using WITH CONNECTION. Use the WITH CONNECTION script as follows:
If you want to overrule the endpoint address use URL "https://...." option
If you want to add another Query-string (filter for example) use QUERY "filter" "id eq cde61c53-b536-46f3-8538-6470042e4160" (QUERY takes 2 more parameters, key and value)
If you want to add another header-key use HTTPHEADER
Note: You can NOT change the method (GET/POST), you need another data connection if you have to use the other
Here is my example of getting the info just for the current app:
Add this row before the "LIB CONNECT TO ..." statement:
LET vAppId = DocumentName();
This will assign the app GUID to the variable.
Modify the last row of the first block as follows:
Note: the variable $(AppId) is slided into the filter. QUERY xrfkey;
When you execute the script, you will get the app info from the QRS API loaded as a table datamodel:
Now you can use some of your scripting skills to get, for example, to check which tags the given app has and do something:
FOR v = 1 TO FieldValueCount('name_u0')
LET vTag = FieldValue('name_u0', 1);
IF vTag LIKE 'byCSW' THEN
TRACE --- this app has the tag of the tags ---;
More Advanced Script Example or QRS API
In the following example I am loading the list of all tasks for a given app. For the tasks I also want a 1:n-List of Custom Properties (if any) and Tags (if any). The returned Json structure would be complex (8 tables for the qrs endpoint /qrs/reloadtask/full):
Deselect what you don't need. I also unchecked a lot of unneeded columns. You better spend a few minutes in the "select data" dialog of the Data Connector than in the script below. To see which fields I skipped I commented them out in the code below. I also introduced "nice field names" like "tag.name" or "task.id" instead of auto-generated names such as "name_u4", "id_u6" ...
Finally, I joined some tables to have only 3 relevant ones after this.
Here is the sample script:
LET vAppId = DocumentName();
LET vXrfkey = Left(KeepChar(Repeat(Rand(),10),'0123456789'), 16);
TRACE Onetime Xrfkey = $(vXrfkey);
LIB CONNECT TO 'QRS full app info (qmi-qs-aai_vagrant)';
"id" AS "id_u6",
// "createdDate" AS "createdDate_u0",
// "modifiedDate" AS "modifiedDate_u0",
// "modifiedByUserName" AS "modifiedByUserName_u0",
"name" AS "name_u2",
// "privileges" AS "privileges_u5",
// "schemaPath" AS "schemaPath_u0",
// "id" AS "id_u0",
FROM "definition" PK "__KEY_definition" FK "__FK_definition")
FROM "customProperties" PK "__KEY_customProperties" FK "__FK_customProperties"),