Managing personal and private content
Introduction
When an end user leaves your company, what happens to the analysis they create and curate? When you need to extract and promote a sheet from a Sense app in a managed space to a base-level asset, how do you do that?
In this tutorial, you are going to learn how to configure an OAuth machine-to-machine client to access resources located in personal spaces. In addition, you will learn how to access private content like sheets in a Qlik Sense analytics application to copy/paste it into another app and publish it.
Get started
To complete this tutorial you need:
- A Qlik Cloud enterprise tenant.
- Access to create an OAuth machine-to-machine client in the management console.
- Knowledge of JavaScript or
qlik-cli
.
For the rest of this tutorial, the OAuth machine-to-machine client will be referred to as the private content bot.
1.0.0 Configuration
1.1.0 Create an OAuth client
Access the management console in your Qlik Cloud tenant and create a machine-to-machine OAuth client.
When you create the OAuth client:
- Select the
admin.apps
scope. - Select the
admin_classic
scope. - Check the machine-to-machine grant type checkbox.
Save the OAuth client per the instructions in the OAuth client tutorial. Record
the client_id
and client_secret
for later use.
You have created the private content bot.
1.2.0 Create a context in qlik-cli
Follow the directions in the qlik-cli-contexts tutorial to enable the private content bot with qlik-cli.
1.2.1 Create a host configuration in qlik-api
The qlik-api
is a typescript typed library for accessing Qlik Cloud REST APIs
and the Qlik Analytics Engine. The library works as an ES module only, so you
may have to configure your package.json
to support type: 'module'
.
The hostConfig
variable is where you input the information to connect to your
Qlik Cloud tenant. Adding the scope
property is optional as machine-to-machine
tokens will automatically scope to their configuration in the management
console.
Set qlik-api
to use the hostConfig
by issuing the
auth.setDefaultHostConfig()
command with the hostConfig
variable as a
parameter.
import { auth, spaces } from "@qlik/api";
const hostConfig = {
host: "<your-tenant>.<region>.qlikcloud.com",
authType: "oauth2",
clientId: "<client-id>",
clientSecret "<client-secret>",
scope: "user_default admin.apps admin_classic",
};
auth.setDefaultHostConfig(hostConfig);
You can begin issuing requests as the private content bot using qlik-api.
2.0.0 Using the private content bot with qlik-api
2.1.0 List all analytics applications in personal spaces
In this example, the private content bot uses qlik-api
to list all the
analytics applications in personal spaces. In addition, the bot obtains the
name of the application owner.
import { auth, users, items } from "@qlik/api";
(async () => {
auth.setDefaultHostConfig(hostConfig);
//get apps in personal spaces
const itemList = await items
.getItems({
resourceType: "app",
spaceType: "personal",
limit: 100,
})
.then((res) => {
return res.data;
});
//use a promise to return a new array of apps containing the app owner's name
let appList = await Promise.all(
itemList.data.map(async (item) => {
return {
id: item.id,
resourceId: item.resourceId,
name: item.name,
ownerId: item.ownerId,
ownerName: await getUserName(item.ownerId),
};
}),
);
console.log(appList);
process.exit();
})();
//helper function that returns a name for the supplied userId
async function getUserName(userId) {
const user = await users.getUser(userId);
return user.data.name;
}
2.2.0 List a user’s private sheets in an analytics application
import { auth, qix} from '@qlik/api';
const appId = "ff345764-ee83-4488-8637-e93ddb7ccc47";
(async () => {
auth.setDefaultHostConfig({
authType: "oauth2",
host: "<your-tenant>.<region>.qlikcloud.com",
clientId: "<client-id>",
clientSecret "<client-secret>",
scope: "user_default admin.apps admin_classic",
});
const app = await qix.openAppSession(appId).getDoc();
const sheets = await app.getSheetList();
for(let sheet of sheets) {
console.log(sheet.qMeta.title, sheet.qMeta.privileges, `Current publish status is:${sheet.qMeta.published}`);
}
process.exit();
})();
2.3.0 Publish a private sheet
import { auth, qix } from '@qlik/api';
const appId = "ff345764-ee83-4488-8637-e93ddb7ccc47";
const sheetId = "fa5fc527-3717-4a90-88f0-c6e4638c60b0";
(async () => {
auth.setDefaultHostConfig(hostConfig);
const app = await qix.openAppSession(appId).getDoc();
const sheet = await app.getObject(sheetId);
try {
await sheet.publish();
await app.doSave();
console.log("Published");
} catch (error) {
console.log(error);
}
process.exit();
})();
2.4.0 Duplicate a sheet in an application
import { auth, users, items, qix, apps } from '@qlik/api';
const appId = "ff345764-ee83-4488-8637-e93ddb7ccc47";
const sheetId = "fa5fc527-3717-4a90-88f0-c6e4638c60b0";
(async () => {
auth.setDefaultHostConfig(hostConfig);
const app = await qix.openAppSession(appId).getDoc();
const sheet = await app.getObject(sheetId);
const sheetPropsTree = await sheet.getFullPropertyTree();
//duplicate the sheet by creating a new object;
//if you are inserting into a new app, you do not need to
//change the object Id.
sheetPropsTree.qProperty.qInfo.qId = "randoString21";
//create the new sheet by supplying the QProperty attribute.
const newSheet = await app.createObject(sheetPropsTree.qProperty);
//get the properties so you can confirm the object id
const newSheetProps = await newSheet.getProperties();
console.log(newSheetProps);
//save the app to persist changes
await app.doSave();
//run apps.updateAppObjectOwner to change the owner of the sheet
try {
const co = await apps.updateAppObjectOwner(appId,newSheetProps.qInfo.qId,{"ownerId": "64fb23dd7a7b40079f26346c"});
await app.doSave();
console.log(co);
} catch (error) {
console.log(error);
}
//sheet will show up in private. This example was performed
//on an app in a managed space.
process.exit();
})();
Conclusion
These are just a few of the different management actions you can take with the new private content bot.