I am trying to implement dynamic masking on a text field.
I created a new custom user, test1, (see picture below) and granted it a role called view_pi (see picture below).
I also created the following masking policy and applied it to the hobby column.
I don't understand why user text1 in view_pi role still has the hobby column masked -> see 3rd picture below.
Would appreciate any help.
Thank you
Yoram
Making policy:
create or replace masking policy text_field_mask as (val string) returns string ->
case
when current_role() in ('view_pi') then val
else '**Masked**'
end;
alter table if exists family modify column hobby set masking policy text_field_mask;
Problem solved with the help of Marina from the support center in Amsterdam.
Role name comparison is case sensitive.
Roles are stored in the DB in upper case and my masking policy used lower case letter for the role.
"view_pi" does not equal "VIEW_PI".
Have fun!
Related
I have a custom object consent and preferences which is child to account.
Requirement is to restrict duplicate record based on channel field.
foe example if i have created a consent of channel email it should throw error when i try to create second record with same email as channel.
The below is the code i have written,but it is letting me create only one record .for the second record irrespective of the channel its throwing me the error:
Trigger code:
set<string> newChannelSet = new set<string>();
set<string> dbChannelSet = new set<string>();
for(PE_ConsentPreferences__c newCon : trigger.new){
newChannelSet.add(newCon.PE_Channel__c);
}
for(PE_ConsentPreferences__c dbcon : [select id, PE_Channel__c from PE_ConsentPreferences__c where PE_Channel__c IN: newChannelSet]){
dbChannelSet.add(dbcon.PE_Channel__c);
}
for(PE_ConsentPreferences__c newConsent : trigger.new){
if(dbChannelSet.contains(newConsent.PE_Channel__c))
newConsent.addError('You are inserting Duplicate record');
}
Your trigger blocks you because you didn't filter by Account in the query. So it'll let you add 1 record of each channel type and that's all.
I recommend not doing it with code. It is going to get crazier than you think really fast.
You need to stop inserts. To do that you need to compare against values already in the database (fine) but also you should protect against mass loading with Data Loader for example. So you need to compare against other records in trigger.new. You can kind of simplify it if you move logic from before insert to after insert, you can then query everything from DB... But it's weak, it's a validation that should prevent save, it logically belongs in before. It'll waste account id, maybe some autonumbers... Not elegant.
On update you should handle update of Channel but also of Account Id (reparenting to another record!). Otherwise I'll create consent with acc1 and move it to acc2.
What about undelete scenario? I create 1 consent, delete it, create identical one and restore 1st one from Recycle Bin. If you didn't cover after undelete - boom, headshot.
Instead go with pure config route (or simple trigger), let the database handle that for you.
Make a helper text field, mark it unique.
Write a workflow / process builder / simple trigger (before insert, before update) that writes to this field combination of Account__c + ' ' + PE_Channel__c. Condition could be ISNEW() || ISCHANGED(Account__c) || ISCHANGED(PE_Channel__c)
Optionally prepare data fix to update existing records.
Job done, you can't break it now. And if you ever need to allow more combinations (3rd field) it's easy for admin to extend it. As long as you keep under 255 chars total.
Or (even better) there are duplicate matching rules ;) give them a go before you do anything custom? Maybe check https://trailhead.salesforce.com/en/content/learn/modules/sales_admin_duplicate_management out.
In my jobs I'd like every source/sink/operator should to have uid and name property defined for easier identification.
operator.process(myFunction).uid(MY_FUNCTION).name(MY_FUNCTION);
Right now I need to manually review every job to detect missing settings. How can I tell Flink to fail job if any name or uid is not defined?
Once you get a StreamExecutionEnvironment you can get the graph of the operators.
When you don't define a name Flink autogenerates one for you. In addition if you set a name, in case at least of sources or sinks, Flink adds a prefix Source: or Sink: to the name.
When you don't define a uid, the uid value in the graph at this stage is null.
Given your scenario, where the name and uid are always the same, to check all operator have been provided with the name and uid you can do the following:
getExecutionEnvironment().getStreamGraph().getStreamNodes().stream()
.filter(streamNode -> streamNode.getTransformationUID() == null ||
!streamNode.getOperatorName().contains(streamNode.getTransformationUID()))
.forEach(System.out::println);
This snippet will print all the operator that doesn't match with your rules.
This won't work in the 100% of cases, like using a uid which is a substring of the name. But you have here a general way to access to the operators information and apply the filters that fits in your case and perform your own strategy.
This snippet can de used as part of your CI or use it directly in your application.
The idea is to accomplish the following when a new user is added:
Create a new group (OG)
Save it
Add user to saved group (OG)
Assign group role (OG)
I am using Rules with Organic Groups. All is fine apart from assigning the group role. I know you can add general system roles but does anyone know how to assign a group (OG) role programmaticaly so it happens automagically?
Any help much appreciated
I use the following custom php action on a rule, to add user to group and assign OG role.
OG role numbers appear to be in order of OG roles, as viewed through admin/config OG entries.
global $user;
// Load the user we want to add to the group
$account = user_load($user->uid);
// Add the user to the group - hard code group 18 which is my group as cant
// get PID from Ubercart order, to pull gid from nid. User, current user, active,
// etc., all default in 2nd array() param to og_group.
og_group(18);
// Changes the users role in the group (1 = non-member, 2 = member, 3 = administrator member, 4 = Forum Administrator)
og_role_grant(18, $account->uid, 2);
Note, OG role 4 (forum administrator) is a custom OG role I created. Also, 'member' (2) is the default, I believe, but I put this in so I'd remember how to allocate other OG roles if I needed to in future.
I'm not a php guru unfortunately, and I still havent worked out how to pull the pid from the node of the Ubercart product ordered so I can get its gid and hence not hard code the gid of 18.
Hope the above code snipped (og_role_grant mainly) works for you as a rule action custom php code snippet (remember not to include the php tags at top and bottom as rules does this for you).
If you have any thoughts on my problem of getting the gid of the ordered ubercart product, as above, please feel free to share. :)
Best wishes
There is a proposed Organic Group patch that add this functionality to the Organic Group Rules integration.
You can find the patch here: https://drupal.org/node/1327326
It adds Grant and Revoke role actions.
You can use og_role_grant($group_type, $gid, $uid, $rid) to assign a role to a user into an organic group programmatically.
To use this with rules, you can define a custom action using hook_rules_action_info() .
What I am looking to do is Make it the "Account" name field require a unique name.
Basically If one of my reps tries to create an account, and that account all ready exists it tells them no that account all ready exists.
Salesforce tells me this funicality is not build into sales force. Any help or dirrection would we wonderfull.
Make a new text field, call it Name__c. Mark it as unique, length... probably 80, same as Name field length.
Create new Workflow rule with condition ISNEW() || ISCHANGED(Name) || ISBLANK(Name__c) and the action should be a field update that simply has Name in the formula that determines new value.
Remember to activate the workflow and to fill in the newly created field because it will be blank for all your existing accounts!
Your call if you want to show the field on page layouts (it's quite "technical" so could be hidden). If you do - it's a good idea to make it readonly!
You can use this validation:
AND(CONTAINS(VLOOKUP( $ObjectType.Account.Fields.Name , $ObjectType.Account.Fields.Name, Name), Name), OR(ISNEW(), ISCHANGED(Name)) )
Salesforce offers duplication management for this purpose.
You just set up Matching Rules and Duplicate Rules for your Account object in Setup > Administration Setup > Data.com Administration > Duplicate Management.
Link: https://help.salesforce.com/apex/HTViewHelpDoc?id=duplicate_prevention_map_of_tasks.htm&language=en_US
You could write a trigger to prevent duplicates. It'd be a "before insert" trigger that queried for existing accounts with the same name. If an Account name already exists, you'd call addError() on the new Account record, preventing the insert from continuing.
Have you searched the AppExchange for solutions? Might want to check out something like DupeCatcher
You could always make a custom field to contain the account name (something like "Business Name") and then ensure that's required and unique.
You'd need to do some basic Data Loader gymnastics to move your account names to the new field, and come up with a strategy for populating the existing Name field for accounts.
AND(VLOOKUP($ObjectType.Object_Name.Fields.Name, $ObjectType.Object_Name.Fields.Name, Name) = Name, OR(ISNEW(), ISCHANGED(Name)))
This is an APEX code related question and is specific to a VisualForce controller class.
Question
I am trying to update a record with a known AccountId. However, when I set the ID in the sObject declaration SalesForce is appending the string "IAR" to the end of the ID!
Can someone please let me know what I am doing that is wrong and if I am going about this in the wrong way than what is the correct way to update a record from a custom method, outside of quicksave() or update().
Description
So basically, the user will come to this page with the id encoded and it will either have an id or a level. This is handled by the function decode() which takes a string; "id" / "level". I then create an Account variable "acc" which will be used to store all of the Account information before we insert or update it with the statement "insert acc;". Since, I cannot set the ID for "acc" with "acc.id = salesForceID" I have decided to set it when "acc" is created. The following APEX code occurs in the constructor when it is declaring the "acc" variable.
URL Variable Passed
/application?id=001Q000000OognA
APEX Controller Class (Abridged)
salesForceID = decode('id');
debug1 = 'salesForceID: ' + salesForceID;
acc = new Account(id = salesForceID);
debug2 = 'Account ID: ' + acc.id;
Debug Output
salesForceID: 001Q000000OognA
Account ID: 001Q000000OognAIAR
Comments
I apologise for the brevity of the code given, this is for security reasons. I am basically trying to set the ID of the acc before I insert/upsert/update it. I appreciate any explanations for why it could be appending "IAR" and or any alternate ways to update a record given an input AccountId. I do understand that if you pass the id in as a URL variable that SalesForce will automatically do this for you. However, I am passing more than one variable to the page as there are three separate use cases.
Thanks for your help.
001Q000000OognA is the "standard" 15-character Salesforce ID. 15-character ID's are case-sensitive.
001Q000000OognAIAR is the case-insensitive 18-character version of that ID.
Either one is fine. You do not need to worry about the difference. If for some reason you really need to use the 15-character version in parameters etc, you can safely truncate the last 3 digits.
More information here: http://www.salesforce.com/us/developer/docs/api/Content/field_types.htm