🔒 WEBCON Privileges

🔒 WEBCON Privileges

There comes a time, when WEBCON gets more popular in the company, and lots of users are working in the system. In this post, I'll guide you through the process of how to determine which users have access to specific applications/processes/workflows/forms within WEBCON

So let's start at the beginning - there is a really good matrix showing where you can set user privileges on the WEBCON Community, and there is whole article about it, explaining where you can configure them.

Privileges in WEBCON. This matrix comes from docs, rather than from the community article.

On the left side of the table are scopes, and levels on which you can define privileges - in the parenthesis name of the level in database dictionaries:

  • Global
    • System administrators (AppAdministrator)
    • Business administrators (Admin)
    • Workflow data read-only access (ReadOnly)
  • Application
    • Application Administrator (AppAdministrator)
    • Portal designer (AppDesigner)
    • Application access (Visibility)
    • Metadata access (AppMetadata)
  • Process and Workflow/Form combination
    • Business administrator (Admin)
    • Access and edit all workflow instances (Modify without delete)
    • Launch new workflow instances (AddNew)
    • Access all workflow instances (ReadOnly)
    • Access all workflow instances (excluding attachments) (ReadOnly without attachments)
    • Manage archive (haven't found data)
    • Designer Desk edit in Portal (Designer Desk edit in Portal)

So the granularity is really nice, there is also possibility to grant/remove privileges per each document - I'll talk about it later, but I wont focus on this case. We can set them per user, or per group which might come from different sources:

  • Active Directory
  • Azure Active Directory
  • BPS Users
  • Custom LDAP Server

We have to consider them based on our environment - in my case I have AAD, and BPS Users and groups, so I'll focus on those. There is a chance, that it will work on AD and LDAP too, but can't guarantee that.

Where to find what we need?

There is really useful document on BPS_Content structure.

BPS_Content is the database with our answers, we will use quite a few tables from here:

A really neat feature of Microsoft SQL Server Studio is that you can create schema diagrams there in no time.
Securities diagram.
All of the data you will see in examples is fake, generated by Chat GPT in this chat. That's another use for this LLM, which i really like.

Users and groups

There is a lot to do, I'll show and explain first few parts of the SQL needed, and at the end there will be combined CTE. At first we need users and groups, so those are queries that returns them:

  Users (COS_ID, COS_DisplayName, COS_BpsID) AS (
            COS_AccountType IN (
                1 -- AAD User

Query to get all the users.

COS_ID COS_DisplayName COS_BpsID
1048 Alice Johnson [email protected]
1049 Andrew Wilson [email protected]
1050 Benjamin Lewis [email protected]
1051 Christopher Moore [email protected]
1052 Daniel Johnson [email protected]
    Groups (COS_ID, COS_DisplayName, COS_BpsID) AS (
            COS_AccountType IN (
                4, -- BPS Group
                2 -- AAD Group

Query to get all groups.

COS_ID COS_DisplayName COS_BpsID
1077 AAD DC Administrators 16e785e8-2f98-4574-803a-b046e025df21
1078 CEO 12c453e9-e85c-4ab2-b5f3-a5f06de60f49
1079 HR 9f40b699-1a06-44eb-8375-3b1dcfd07227
1080 Marketing 416b2dee-547e-4d30-9263-6e388957728c
1081 Sales 3a17942f-4804-4b82-a09d-4d82429a818c

This might require slight change depending on environment - in my case, this filter was good enough to separate which records are users, and which are groups.

    UsersAndUsersInGroups (COS_UserBpsID, COS_GroupBpsID, UserName, GroupName) AS (
            Users u JOIN
            CacheOrganizationStructureGroupRelations c ON u.COS_ID = c.COSGR_UserID JOIN
            Groups g ON g.COS_ID = c.COSGR_GroupID
        UNION ALL


Query to get users and groups useres, thankfully without recursion, as it's already flattened.

COS_UserBpsID COS_GroupBpsID UserName GroupName
[email protected] 1a31cc59-0b8f-4327-841e-fa4056de63b3 William Garcia Finance
[email protected] f2d4672a-56ec-44ba-864f-9acc9c06b427 William Garcia All Employees
[email protected] NULL William Garcia NULL

Global Privileges

This provides us first part of the question - what users are in the system. Now going to second question - where do they have privileges. At the end we want to have those columns Scope, Level, ID, UserID, UserName, GroupID, GroupName, APP_Name, DEF_Name, WF_Name, DTYPE_Name, COM_Name. We will start with the highest scope - global.

    GlobalPrivileges (Scope, Level, ID, UserID, UserName, GroupID, GroupName, APP_Name, DEF_Name, WF_Name, DTYPE_Name, COM_Name) AS (
            'Global' As Scope,
            NULL As APP_Name,
            NULL As DEF_Name,
            NULL As WF_Name,
            NULL As DTYPE_Name,
            NULL As COM_Name
            WFConfigurationSecurities JOIN
            UsersAndUsersInGroups u ON (u.COS_UserBpsID = CSC_USERGUID AND u.COS_GroupBpsID IS NULL) OR u.COS_GroupBpsID = CSC_USERGUID JOIN
            DicConfigurationSecurityLevels d ON CSC_LevelID = d.TypeID
            CSC_IsGlobal = 1

Query to get global scoped privileges.

Scope Level ID UserID UserName GroupID GroupName APP_Name DEF_Name WF_Name DTYPE_Name COM_Name
Global AppAdministrator NULL [email protected] Lúmenn NULL NULL NULL NULL NULL NULL NULL
Global AppAdministrator NULL [email protected] William Turner NULL NULL NULL NULL NULL NULL NULL

There is a lot of NULL values due to the fact that there is no application, process, definition, workflow, form or company data in this scope - the amount of NULL's will be smaller with increasing granularity - we need them, to UNION ALL of the privileges at the end.

It's mostly regular query, but we have one specific JOIN condition (u.COS_UserBpsID = CSC_USERGUID AND u.COS_GroupBpsID IS NULL) OR u.COS_GroupBpsID = CSC_USERGUID - we want to join on COS_UserBpsID only if it's not a group, because in UsersAndUsersInGroups user identifiers are not distinct - they might be there multiple times - if the user is member of any group.

Further on it's mostly the same thing - we are just joining different tables to get application/process/workflow/form. The final version is available here:

GitHub - lumenn/webcon-privileges-lookup
Contribute to lumenn/webcon-privileges-lookup development by creating an account on GitHub.

In the future i might prepare some report with BI tool, if it will see the light of the day there will be a post on that for sure.