toggle between user filters? - tableau-api

Say I have two groups: Group 1 & Group 2
Group 1 needs access to a value in the [Business Unit] dimension, lets say "Degree" [Business Unit], while Group 2 needs access to just one value in [department] dimension, lets say "Human Resources" [Department].
I can't have two user filter sets in my filter pane because it'll conflict and just give me a blank view of my data. Is there a way I can toggle between them based on which group is trying to access the dashboard?
if ISMEMBEROF('Group 1') then [User Filter Option (Business Unit])
else [User Filter Option (Department)] end
didn't end up working. Any ideas?

Here are some documents on how to set up RLS - Row Level Security on multiple dimensions
Fast overview:
https://help.tableau.com/current/pro/desktop/en-us/publish_userfilters.htm
More details with examples:
https://tableauandbehold.com/2020/12/09/quick-explanation-of-row-level-security-in-tableau/
Underlying Theory:
https://www.tableau.com/learn/whitepapers/row-level-security-entitlements-tables
Wade

Related

Doctrine : PostgreSQL group by different than select

I have two tables :
user and activityHistory (that has a key to the user)
I am trying to query activityHistory while grouping by user and postgreSQL does not allow me to do that WHILE Sqlite does allow me
return $qb
->select('a.id')
->leftJoin('a.user', 'user')
->leftJoin(
ActivityHistory::class,
'b',
'WITH',
'a.id = b.id AND a.createdAt > b.createdAt'
)
->groupBy('user.id')
->orderBy( 'a.createdAt','ASC' )
->getQuery()->getArrayResult();
I am getting this error only with postgreSQL : Grouping error: 7 ERROR: column "a0_.id" must appear in the GROUP BY clause or be used in an aggregate function
The point is I don't want to groupBy activityHistory id, I only want it to be selected, how can I do ? (I heard about aggregate but I think this works only with functions like SUM etc)
First of all, let's clarify how aggregation works. Aggregation is the act of grouping by certain field(s) and selecting either those fields or calling aggregation functions and passing ungrouped fields.
You misunderstand how this works - hence the question -, but let me provide you a few very simple examples:
Example 1
Let's consider that there is a town and there are individuals living in that town. Each individual has an eye color, but, if you are wondering what the eye color of the people of the town is, then your question does not make sense, because the group itself does not have an eye color, unless specified otherwise.
Example 2
Let's modify the example above by grouping the people of the town by eye color. Such an aggregation will have a row for all existent eye colors and you can select the eye color, along with the average age, number of individuals, etc. as you like, because you are grouping by eye color
Your example
You have users and they are performing actions. So, an activity is performed by a single user, but a user may perform many activities. So, if you want to group by your user id, then the "eye color" that you are not grouping by here is the history id.
You will have a single record for any user, so you are grouping multiple history items into the same row and after the grouping, asking about the history item's id does not exist.
But, you can use string_agg(some_column, ',') which will take all the values you have and put them all into a string of values separated by comma.
You can explode(',', '$yourvalues) in PHP to convert such a value into an array.

how to create multiple filters from one dimension tableau (10)?

I have a two dimensions with the following data set
Original Dimension
I would like to create two filters that can be used to filter my dashboard. These two filter would be called - "Product_Type" and "Product" and should have the following drop downs:
Filter Breakdown
To summarize, I am looking for a way to take my original dimension and create the filter breakdowns so that in my dashboard I can have two filter (Product_type and Product). When i click on the Product_type filter, i should be able to see "overall", "fruits", "vegetable" and "leafy. Based on my selection , the Product filter should automatically show only the relevant values - i.e. if i picked "leafy" it should only show "spinach" and "kale". Finally if i select "kale" my entire dashboard should change accordingly.
Looking for a way to do this without drastically affecting the performance.
update: i was able to achieve this by creating multiple parameters and then using the pop window technique (https://vimeo.com/107352893) - but this has affected my workbook performance very badly. Need another solution!!
You should be able to accomplish your desired functionality by creating a calculated field for product type and a CASE statement to classify the products based on the product type you specified your image.
Further, filters can be configured to display available values based on the other filters in place. I would recommend having your Product Type filter a the "context" or "data-source" level, and your product filter at the lowest level, so that the selectable options for the product filter can be displayed using the "only relevant Values" option and limits the products that can be chosen.
Please see the following link for some more information on filtering hierarchies
Performance Related
General Filtering
Blog Post
"Only relevant values - Specifies which values to show in the filter. When you select this option other filters are considered and only values that pass these filters are shown. For example, a filter on State will only show the Eastern states when a filter on Region is set. You can use the toggle at the top of the filter card to switch between this option and the All Values in Database option.
All values in database - Specifies which values to show in the filter. When you select this option all values in the database are shown regardless of the other filters on the view.
All values in context (Tableau Desktop only) - When one of the filters in the view is a context filter, select this option on a different filter to only display values that pass through the context filter. For more information, see Improve View Performance with Context Filters."

Tableau Data Security for Sales Revenue

I want the salesrep to see both theirs and OVERALL TEAMS PERFORMANCE. Is it possible to create a TOGGLE SWITCH : ME/TEAM...when they click on ME - it shows them their revenue and when they click on TEAM - it show overall team revenue. But, they still shouldn't be able to see other salesman revenue...Thanks
Currently, I'm filtering their access to data by their USERNAME using the FULLNAME() function in Tableau. I'm wondering how would the salesrep be able to see the revenue of the TEAM OVERALL which helps them to compare their performance to the team overall
As far as I can tell, with your current setup, you will only be able to display the active sales reps data. This appears to be a requirement for data security. If you want reps to see the overall team data as well, I would create a second data source with aggregated team data, create a view based on this data and place both views side by side on a dashboard.
After that, you could build in the toggle functionality with parameter controls.
Create a parameter. Simple example would be a text input that accepts two values, ME or TEAM. For this example, let's call the parameter Parameter 1.
Set up a conditional calculated field to handle your data security. The condition is based on the parameter. For this example, let's call the calculated field What To Show.
Add a filter, preferably at the data source, for What To Show = True.
The code for What To Show is
if [Parameter 1] = "ME" then [USERNAME] = FULLNAME() END
[USERNAME] of course is whatever your security column is called.
What you are doing here is conditionally applying row-level security based on what parameter your user has selected.

Figuring out DB2 LBAC policies for any user

IBM DB2 has nice LBAC (label based access control) policy. I am not facing problem when creating or using these policies from within the query browser. However, my requirement is a bit different. Using LBAC, let us say that I have created the required security labels and assigned them to the columns and rows in the database tables. Now, Given the access control for the user, I want to find out if a particular label is accessible to that user.
DB2 will internally figure it out and produce the desired results, however I need some solution which would tell me if a particular column/row is accessible to the user, if I am given the user's access level along with the security labels for each column/row. I need some method which does the following:
Find out the security labels for a column [I can do this]
Find out the access controls allowed to the user [I can do this]
Tell if these security labels are accessible for the user [I do not know how to achieve this]
Consider this example:
My sample component:
/*Create the component*/
CREATE SECURITY LABEL COMPONENT ORG_DIVISIONS
TREE ('ORGANIZATION_ADMIN' ROOT, --The admin will have the complete access
'SALES' UNDER 'ORGANIZATION_ADMIN', --The sales department will have acess to the financial information for each unit
'RESEARCH' UNDER 'ORGANIZATION_ADMIN', --The research division will have access to technical specs and design along with certain financial information
'RSM1' UNDER 'RESEARCH', --The research manager 1 will have access to certain design and technical specs and certain financial information (depending on the project he is undertaking)
'RS_ENGG1' UNDER 'RSM1', --The research engineer 1 will have access to certain technical specs (depending on the project he is undertaking)
'MANUFACTURING' UNDER 'ORGANIZATION_ADMIN', --The manufacturing unit will have access to design along with certain financial information
'MFM1' UNDER 'MANUFACTURING', --The manufacturing division manager 1 will have access to certain designs along with certain financial information (depending on the project he is undertaking)
'MF_ENGG1' UNDER 'MFM1' --The manufacturing division engineer 1 will have access to certain designs (depending on the project he is undertaking)
)
My sample policy for the component:
/*Create the policy*/
CREATE SECURITY POLICY ORGANIZATION_POLICY
COMPONENTS ORG_DIVISIONS
WITH DB2LBACRULES
RESTRICT NOT AUTHORIZED WRITE SECURITY LABEL
My sample set of labels:
/*Create the labels from the policy components*/
CREATE SECURITY LABEL ORGANIZATION_POLICY.ORGANIZATION_ADMIN
COMPONENT ORG_DIVISIONS 'ORGANIZATION_ADMIN'
CREATE SECURITY LABEL ORGANIZATION_POLICY.SALES
COMPONENT ORG_DIVISIONS 'SALES';
CREATE SECURITY LABEL ORGANIZATION_POLICY.RESEARCH
COMPONENT ORG_DIVISIONS 'RESEARCH';
CREATE SECURITY LABEL ORGANIZATION_POLICY.RSM1
COMPONENT ORG_DIVISIONS 'RSM1';
CREATE SECURITY LABEL ORGANIZATION_POLICY.RS_ENGG1
COMPONENT ORG_DIVISIONS 'RS_ENGG1';
CREATE SECURITY LABEL ORGANIZATION_POLICY.MFM1
COMPONENT ORG_DIVISIONS 'MFM1';
CREATE SECURITY LABEL ORGANIZATION_POLICY.MF_ENGG1
COMPONENT ORG_DIVISIONS 'MF_ENGG1';
My sample user:
/*Use the defined policies and grant accesses to the users*/
GRANT SECURITY LABEL ORGANIZATION_POLICY.RSM1
TO USER someone FOR ALL ACCESS;
Now, since I defined a tree component, the user someone will have access to entities which are labeled RSM1 or with its children labels (RS_ENGG1 in this case). DB2 knows this and will present me the relevant results if login as user someone and fire queries. But the question is, how can I (as an admin) know which columns/rows would be accessible to user someone? Can this information be retrieved from some security table or figured out somehow?
Regards,
Salil Joshi
I could not find any solution to this problem. What I ultimately did was to find out the security components of the type 'Tree' and 'Array', list their components, and re-constructing the equivalent tree in Java.
1) Find out the labels granted to the user
SELECT
A.grantee
,B.secpolicyname
,c.seclabelname
FROM
syscat.securitylabelaccess A
,syscat.securitypolicies B
,syscat.securitylabels C
WHERE
A.seclabelid = C.seclabelid
AND A.secpolicyid = B.secpolicyid
AND B.secpolicyid = C.secpolicyid
2) Find out the array and tree component elements:
For trees:
SELECT
D.secpolicyname
,B.elementvalue
,B.parentelementvalue
FROM
syscat.securitylabelcomponents A
,syscat.securitylabelcomponentelements B
,syscat.securitypolicycomponentrules C
,syscat.securitypolicies D
WHERE
A.compid = B.compid
AND A.comptype = 'T'
AND A.compid = C.secpolicyid
AND C.secpolicyid = D.secpolicyid
For arrays (note: I could not find the order in which the elements were inserted in the array, but found that doing a selection (select *) rather than projection (select A.a, B.b, ...) helps here. Any better solutions are welcome):
SELECT *
FROM
syscat.securitylabelcomponents A
,syscat.securitylabelcomponentelements B
,syscat.securitypolicycomponentrules C
,syscat.securitypolicies D
WHERE
A.compid = B.compid
AND A.comptype = 'A'
AND A.compid = C.compid
AND C.secpolicyid = D.secpolicyid
3) Generate the list of labels allowed for the user using the above constructs.
One small problem here is that the component elements and the labels created from them might not have same name, and I could not find any mapping for them. I have posted this problem here for the same.

Dynamically change parameters based on the value of another parameter?

I have a crystal 2008 report that allows users to group to two levels.
I have two parameters, using which users can select which attribute they want to group on.
The two params are of type string and the list of values is static. Both levels have the same options to group on.
Is there someway to filter the list based on what they selected for param 1. So that they cannot group on the same thing twice.
I don't think it's possible. You can cascade dynamic parameters link Country, State but not how you want to.
How many options do they have to choose from? Do they normally choose anything other than a few different combinations from the maximum?
I think you're options are to either leave it as is (allowing them to pick the same thing for both groups). Or create a single parameters which looks like- Group by:
Date, Country
Type, Country
Date, Type
etc
Short answer: not possible.
Options:
create a custom UI that does what you want to do
if the list of grouping fields aren't too long, you could combine the two parameters into a single one, then list the options that you want to support. For example, if you have 3 grouping fields (A,B,C), your single, combined parameter would be A->B, B->A, B->C, C->B, A->C, C->A.