Showing posts with label Salesforce. Show all posts
Showing posts with label Salesforce. Show all posts

Thursday, December 18, 2025

Next year SF migration plan : moving out customer account to AWS , and call SF data with service account

 👀 The most challenging part is about those function with user verification.

My service cloud with MIAW chat , nearly redo due to the user verification function of UV channel.

Learnt legacy chat migration to MIAW 2025 ,

Customize the MIAW with AWS 2026.


Understood why people are moving out from SF , not just price , is they don't put focus on their core cloud core technology anymore.


The debug of LWC still like a mess ( the syntax is super ugly ).

Not to mention still not able to make change of it in the platform , still rely on IDE deployment which super annoying. Oh the Flow is much not user friendly in compare to workflow rules and process builder. Super heavy as well .

The NEW things to replace the old are worse than those old things. 
Lightning loading slower than classic , MIAW worse than legacy-chat which is very hard to persuade customer to "upgrade" .

Will I still recommend people to use SF ? yes for core cloud ONLY to be honest.
The rest new clouds are "horrible" , not to mention the Agentforce which looks like a semi-product . 
 

Saturday, April 26, 2025

The JWK file specification , something about the public exponent : AQAB 

I need to configure Salesforce JWT (JSON Web Token) user verification recently.

And there is a file JWK (JSON Web Key) required .The sample document from Salesforce shown as below : 
Salesforce Reference


{
    "kid":"123456",
    "alg":"RS256",
    "use":"sig",
    "kty":"RSA",
    "x5c":["<Your public certificate>"],
    "y":"y",
    "n":"<Base64-encoded modulus>",
    "e":"<Base64-encoded public exponent>",
    "crv":"crv",
    "d":"d",
    "k":"k"
}

In order to know more about the values , I do another search online do know more about each parameters.
Detail RFC specification 
And to know more about the Salesforce sample document, I get a search about the Salesforce specific file format as well. 
Medium Reference

The public exponent now become a fix value "AQAB".

{
"kid": "{A unique value that identifies the end user}",
"alg": "RS256",
"use": "sig",
"kty": "RSA",
"x5c": [
"{Paste the public certificate value here}"
],
"y": "y",
"n": "{modulus of the public key in Base64 format}",
"e": "AQAB",
"crv": "crv",
"d": "d",
"k": "k"
}

Isn't it a variable, why it can be fixed ?


The answer is related to the kty (Key Type) parameter.

When "RSA" is used as key type, then the public exponent of it is 65537.


Convert 65537 to hexadecimal , we got 0x01000. Then we encode the 0x01000 to Base64 , we got "AQAB". 


In short, the base64 format public exponent of RSA is "AQAB".  
And this value is came from conversion of public exponent of RSA key type.

Quoted from Wiki

"65537 is commonly used as a public exponent in the RSA cryptosystem".


Sunday, January 26, 2025

Salesforce Tricks : Add line break to Tool tips or field-level help in Lightning Experience.

 A tool tip of a field can be difficult to read when there is no line break.

In formula , we can use "BR()" , but in tool tip, there is no formal method
The idea is still in Idea Exchange .

And a user posted a workaround here , using the "Japanese full width space" (\u3000).

Copy this :   [          ]

And put above bracket into the Help text where you need the line break. 


For example:
My line 1 
[          ] My line 2


Magic is done.


Tuesday, October 15, 2024

Salesforce flow or Process deployment : Setting of active and test flow coverage

When deploy a new flow, it is default to be inactive.

But there is a setting to make it active in PROD org called "Process Automation Settings". 


We need to ensure coverage of the automation . It can be check by SOQL to FlowTestCoverage:

To calculate your flow test coverage, determine the number of all active flow versions with or without test coverage.
Single SOQL with + symbol.

SELECT count_distinct(Id) 
FROM Flow 
WHERE Status = 'Active' AND Id NOT IN ( 
SELECT FlowVersionId 
FROM FlowTestCoverage 
)
+
SELECT count_distinct(FlowVersionId) 
FROM FlowTestCoverage

 

Ref :https://help.salesforce.com/articleView?id=sf.flow_distribute_deploy_active.htm&type=5

Wednesday, August 2, 2023

Python Coding : Call Salesforce API using OAuth 2.0 JWT Bearer token Flow 以 Python 代碼實現Salesforce JWT 伺服器簽名驗證

Prequisites : Setup Connected App with  X509 Certification.

預設需要先在Salesforce 上載X509證書。詳細設定連接。(可接受自行簽署版本證書)

Details Set up in Salesforce side : link



#POC of JWT call to API#Colab install library with >> !pip install pyJWT[crypto]

import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
import time
import requests
import json

expTime = int(time.time()) + 900  #Unix Epoch Timestamp Expire time. 15mins buffer
jwt_algorithm = 'RS256'
jwt_private_key_file = '/myPath/server.key'
jwt_payload = {
  "iss": "clientid",
  "sub": "salesforce_username_email",
  "aud": "https://test.salesforce.com",
  "exp": expTime
}

jwt_header = {
  "alg": "RS256",
  "typ": "JWT"
}
salesforceEndpoint = 'https://test.salesforce.com/services/oauth2/token'
api_endpoint = 'https://instance_domain.my.salesforce.com/services/data/v57.0/sobjects/myObject__c'

test_data={
    "description": "PythonSent",
    "language": "en",
    "remarks": "xxx",
    "expiry_time": expTime+900,
    "created_time": expTime
}


def loginSfdc():
    # Load the private key 
    with open(jwt_private_key_file, 'r') as f:
        jwt_private_key = f.read()

    # Generate the JWT token
    jwt_token = jwt.encode(jwt_payload, jwt_private_key, algorithm=jwt_algorithm,headers=jwt_header)
    print('token : ' + jwt_token);
    salesforceUrlParams = {
        'grant_type' : 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion' :jwt_token
    }

    response = requests.post(salesforceEndpoint, params=salesforceUrlParams, verify=False)

    if response.status_code == 200:
        authToken = response.json()['access_token']
        print('return token ' + authToken)
        return authToken
    else:
        print('Request failed with status code:', response.status_code)
        print('Request failed with status code:', response.text)
        return(0)

#function to call
def callSfdc_pocApi(authToken):
    session = requests.Session()
    rheaders = {
    'Authorization': 'Bearer ' + authToken,
    'Content-Type': 'application/json'
    }
   
    response = requests.post(api_endpoint,headers=rheaders, data=json.dumps(test_data))
    returnStr = ''
    if response.status_code == 200:
        data = response.json()
        returnStr = data
    else:
        print('Request failed with status code:', response.text)
        returnStr = response.status_code

    return returnStr

#Main
response1 = loginSfdc()
if not response1 == 0:
    response2 = callSfdc_pocApi(response1)
    print ("OK")
    print(response2)
else:
    print ('Failed to Login')

Friday, January 13, 2023

Salesforce concept : Limitation of Rollup Summary and Validation Rule

Question : Rollup summary CANNOT be used in formula field ?
Answer : No .
Rollup Summary can be used to group field values of child record .

Even thought it is formula type field , however ,
grouped field values CANNOT be cross-object formula field.


Question : How to validate the field values changed by Approval process ?
Answer : Validation is NOT a choice . Since field update fired by approval process will NOT initiate validation rule. (More explicit answer from google  , Validation Rules fire before workflow rules, so the record has to meet the validation rule criteria before the workflows get a chance to run. So, the validation rule will not work when you update the workflow field.)

Tigger can be used to validate the field values changed by approval process.

Tuesday, June 14, 2022

Salesforce Administration : 2022 Spring email about "Salesforce email verification" from support@salesforce.com SFDC Salesforce 電郵認證郵件是釣魚嗎?

Recently some of the users receiving email from support@salesforce.com with subject "Salesforce email verification". A link is inside that email , users worry it may be phishing email ,so they come to check .

Luckily, it is not a phishing email . From official announcementprior to the Summer '22 release , users may be asked to verify their email .


To get the list of user who may get the mentioned verification email ,s
ystem administrators may use SOQL below :

SELECT Name from User where id IN (SELECT UserId FROM TwoFactorMethodsInfo where HasUserVerifiedEmailAddress = false)


Error message
"sObject is not supported" may be shown if your account do NOT have Manage Multi-Factor Authentication in API permission.

To enable this permission

1.    Go to Setup -> Manage Users -> Permission Sets , click New to create a new permission set.

2.    Select "System Permissions" . 


3.    Click "Edit" , scroll down to items below ,and checked the box. Then save.

        -    Manage Multi-Factor Authentication in API
       -    Manage Multi-Factor Authentication in User Interface




4.    Add the permission set to a user account you use to run the SOQL by using "Assign" button.

5.    Click "Done" to save the setting.

6.    Run the SOQL again.





Tuesday, May 24, 2022

Salesforce Apex Code : Add or Remove ALL (multiple) field permissions of User Profile 快速完成加入或移除個別用戶配置的編輯權限

 Sometimes we may need to update ALL field permission of a user profile due to different purpose, like audit requirement or ISO requirement. 

It can be very time-consuming to do it in UI level . For example, auditor asked to block ALL field "edit" permission of all "Clerk" profile user. You have to go to every object, and untick each field's security checkbox . There is a better way to handle this batch permission update , using "Apex program"


Code below demonstrate how to remove Clerk user's field edit permission right of multiple objects .

   

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Multiple object names into the list
List<String> validTypeList = new List<String>{'Account','Case','Contact','CustomObj__c'}; 
//ClerkUser can be replaced by any profile name
//Use PermissionsRead if "Read" permission is needed
List<FieldPermissions> fpList = [SELECT SobjectType, Field, PermissionsEdit, Parent.ProfileId 
FROM FieldPermissions 
WHERE SobjectType IN :validTypeList AND PermissionsEdit=TRUE
AND ParentId IN (SELECT Id FROM PermissionSet WHERE PermissionSet.Profile.Name = 'ClerkUser')];
if(!fpList.isEmpty()){
    List<FieldPermissions> updatefpList = new List<FieldPermissions>();
    for(FieldPermissions fp:fpList){
        fp.PermissionsEdit = false;
        updatefpList.add(fp);
    }
    update updatefpList;

   //Print Total field edit permissions REMOVED
    system.debug('UpdatefpList Edit Permission - ' + updatefpList.size()); 
}

Thursday, January 13, 2022

Salesforce concept : Validation rule does not fired after approval process field update

Validation rule will not be fired by Workflow rule or Approval Process field update based on document.

Both API level and UI level change of record honored validation rule , but field update is an exception.

Which means , if you have an validation rule block field_ABC value to be "ABC", if you used a field update to do this, the value of  field_ABC can be set as "ABC".



Official IdeaExchange 1

"because updates to records based on workflow rules doesn't trigger validation rules,workflow rules can invalidate previously valid fields "


Official IdeaExchange 2




Wednesday, January 12, 2022

Salesforce Apex code to detect Chinese or Japanese characters 在字串中尋找漢字 包含中文字 或 日文字

 Sometimes we have to identify the language character inside string . Code below shows how to use Apex code to identify whether a specific string contains "Hanzi" or not . 

#Please be reminded that "Hanzi" NOT just detect Chinese characters , it may also include Japanese Hanzi.  

1
2
3
4
5
6
//true if contain chinese or japanese hanzi
public static Boolean containsChineseCharacters(String InputString){
    Pattern p = Pattern.compile('\\p{IsHan}');
    Matcher m = p.matcher( InputString );
    return m.find();
}

Monday, May 31, 2021

Salesforce Permission : Manual Share Record using Apex Bulk API 分享單筆資料代碼

 

 
There are different way of sharing a "private" object record in sfdc.
Include using inherit role hierarchy ,sharing rule , or pressing custom button "Sharing"
on record detail page in user interface. 

Codes below try to use apex API to do the same thing as the "Sharing" button.
#Salesforce分享單筆資料代碼
 

    // Create new sharing object for the custom object named MyCustomObject.
      MyCustomObject__Share myCustomObjectShr  = new MyCustomObject__Share();
   
      // Set the ID of record being shared.
      myCustomObjectShr.ParentId = recordId;
        
      // Set the ID of user or group being granted access.
      myCustomObjectShr.UserOrGroupId = userOrGroupId;
        
      // Set the access level.
      myCustomObjectShr.AccessLevel = 'Read';
        
      // Set rowCause to 'manual' for manual sharing.
      // You may change to other row cause if you have created other sharing reason.
      myCustomObjectShr.RowCause = Schema.myCustomObject__Share.RowCause.Manual;
        
      // Insert the sharing record and capture the save result. 
      Database.SaveResult sr = Database.insert(myCustomObjectShr,false);
 
      // Process the save results.
      if(sr.isSuccess()){
         // Indicates success
         System.debug(LoggingLevel.INFO, 'Done');
      }
	else{
          // read first save result error.
         Database.Error err = sr.getErrors()[0];
         System.debug(LoggingLevel.ERROR, 'Error code :' + err.getStatusCode() );
      }

Sunday, April 25, 2021

Salesforce Record Security : Troubleshoot the Insufficient Privileges Error 檢查 Salesforce 權限不足錯誤

Insufficient Privileges Errors often shown when user attempts to access the record that he/she does not have right permission to read or edit .

Procedure Quick Notes :
(Obj.) User Profile > Permission Sets > (Rec.) OWD > Sharing Rules > Manual Sharing 

First of ALL , make sure the user REALLY does not have the right permission by SOQL below :

SELECT RecordId, HasReadAccess, HasEditAccess FROM UserRecordAccess WHERE UserId = [theUserID] AND RecordId = [theRecordID]

Then , try to check from Object level permission to Record level permission.
*If user can read the record (HasReadAccess=true), then checking of object level security can be skipped.

The security setting about record access in salesforce can be divided into two major levels

  • Object level (*there is Field level under object level)
  • Record level

Setting related to Object level permission 

Object level security determines the baseline level of access for ALL the records in an object.
It controls which object user is permitted to perform CRUD operation in high level.
#CRUD = CREATE,READ,UPDATE,DELETE.

1. Profile
    User profile controls the object and its field permission , it also can be used to grant ALL                       record access/modify permission
  • Way of checking

    1. Setup > Quick Find box > Search Users > User list page > click the User’s profile.
    2. On the Profile overview page, go to Object Settings or Object Permissions.

2. Permission Sets.
    
Permission Sets also controls the same permissions as profile. The main different is the permission         can be assigned to specific single user(s) one by one .

  • Way of checking
    1. Setup > Quick Find box > Search Users > User list page > click the User 
    2. On the user detail page, scroll to the Permission Set Assignments related list and click each permission set.
    3. On the Permission set overview page > Object Settings and review the assigned object permissions.

Common Question : Salesforce do permission sets override profiles ?
#Profile and Permission Sets act as "AND" setting approach .Which means as long as the permission is granted by profile or permission sets either one (or both) , the user owns the permission already.

Answer from internet about Permission Sets VS Profiles 
The settings and permissions in permission sets are also found in profiles, but permission sets extend users' functional access without changing their profiles.

Setting related to Record level permission 


Record level security determines the record accessibility of data that owned (created) by other users.
*Profile and Permission sets could grant "View all record" and/or "Modify all record" to an object. If these two permissions have been chosen, the "ALL" permissions above override the record level setting.


3. OWD ( Organization Wide Default ) 
     OWD specify the basic accessibility of user has to each other’s records. It can be divided
     as two types : Private , Public , [Controlled by Parent] .

  • Way of checking
    1. Setup > Quick Find box > Search Sharing Settings > click Sharing Settings
    2. The top section is about OWD     
  •     Private record only grant access to record owner , and those roles above record owner.
    • For Custom object, the "Grant Access Using Hierarchies" can be disabled (deselected). Which means blocking record access through role hierarchy . 
      • i.e. Blocking supervisor from accessing the data owned by their subordinate. 
  •     Public record can be access by ALL users , and can be categorized into three sub-types : 
    • Read-Only , Read/Write , [Read/Write/Transfer] 
    • Transfer right only selectable to some standard object like Lead , Case etc.
  •     Controlled by Parent record applied to child object that belongs to "Master-Detail"   
          relationship only.
    • If user has access to the parent (master) record, user will be able to view the child (detail).

4. Sharing Rule ( Role , Public Group , Users )
    The rules specify access sharing of Private Object record on top of OWD. While OWD share
    record based on owner role under same hierarchy branch , sharing rule can be used to further share
    record based on different criteria including owner and other record characteristic

    And in contrast to OWD which share record to role above record owner on the hierarchy branch,,
    sharing rule allow to share record to any role(s) and their sub-ordinates , it also enable the sharing
    to specific user(s) or public group .  

  • Way of checking
    1. Setup > Quick Find box > Search Sharing Settings > click Sharing Settings
    2. The middle to bottom section is about sharing rules

  • Share based on Record Owner 
    • Owners can be identified through public groups, roles and roles, and sub-ordinates ,while OWD only identified owner role and OWD does NOT allow cross-branch role  (could be consider as other department) sharing of private record.

      For example , we can share record created by
      Salesman A which is under Sales department to Sales manager(s) and users under Accounting department through sharing rules while OWD may NOT allow record share to Accounting department user under hierarchy below . 
                

  • Share based on Record Criteria
    • This setting enable sharing which is NOT related to record owner, but record's characteristic. 

      For example , we can share opportunity (record) which has Expected Revenue over $1M to marketing manager . 
5. Manual Sharing 
    While OWD and sharing rules can be used to share a group of records , manual
    sharing can be used to share specific single record manually , one by one . 

     Only user(s) has/have "HasAllAccess" can share the record manually to other(s).
    To check who can share the record manually ,use SOQL below :
SELECT UserId, HasAllAccess FROM UserRecordAccess WHERE RecordId = [theRecordID]


  • Way of Checking
    • Record detail page> Sharing button (Classic version)
    • Record > Sharing button > Edit link (Lightning version)
  • Share by Sharing Button 
    • Record owner, role above record owner , user that has "Modify All Data" permission in profile/permission sets and administrator can view all users/groups who has access to that record, and can add share user to that specific record using that button. 
      *Sharing Button can be added via page layout by administrator if you cannot find it .

    • There are different sharing reasons of record, for those using manual sharing , usually the share reason will be "Manual Sharing". Full share reason list can be found in official site.
    • *Record owner change may lead to lost of manual sharing.
  • Share by Apex coding API
    • The default sharing reason of Apex code adding access is the same as using sharing button UI . (Which is Manual Sharing)
    • Administrator can create up to 10 sharing reason for each custom object.
    • Developer may select the custom sharing reason in code, for distinguish purpose.
    • Deleting an Apex sharing reason will delete all sharing on the object that uses the reason.
    • Method to create sharing reason can be found in official site.

Summary
- There are 2 main level of sharing : Object level and Record level. 
- *Field level permission could be set to different profile which controls fields could be access in object.
- Things need to be checked during troubleshoot include Profile , Permission set if user cannot view any record of that object . If there are some records cannot be accessed , then OWD, Sharing Rule and Manual Sharing can be checked.
- Apex Code Sample of Manual sharing  (TODO)

Migrating from Renpy to Godot

 Due to the limitation of renpy in rendering dynamic screen ,  due the the black border it gives in different UI scale resolution , finally ...