I have gone through your question very minutely. After giving profound thoughts based on my capacity, I failed to understand how would you bypass Profile to find the Fields Permissions on any object (Custom or Standard)? As I know with my limited knowledge of Salesforce functionality when we create a custom object with fields without assigning it to any particular profile, Salesforce by default assigned it to the System Administration profile(s). So based on your requirement we can use the Salesforce MetadatAPI Apex wrapper class to query the "Admin" profile and get the field level security of the object in question Because you specified that the object got pushed to the scratch org. We can very much pass the fields information from our client-side JavaScript handler to the server-side @AuraEnabled Apex controller. As per your requirement, "With Sharing" keyword can be omitted to make sure the controller runs on the System Mode.
I have taken the help of Apex Wrapper Salesforce Metadata API created by Andrew Fawcett to demonstrate my PoC. For the detail of copying the Metadata Classes, please follow the instructions of this article Using Named Credentials with the Apex Wrapper Salesforce Metadata API (apex-mdapi). After the successful setup of the Apex Metadata Wrapper class, we can create the following class to test the concept.
public class ApexMetadataFLSCheckingOnProfile {
@AuraEnabled
public static void readProfileFieldSecurity(List<String> Fieldstobeupdated, String objectname)
{
refreshSessionTrick();
MetadataService.MetadataPort service = createService();
String SOQLQuerySelect = 'SELECT ';
String SOQLQueryForm = ' FROM '+ objectname;
String SOQLQueryFields = '';
String SOQLQueryFinalString = '';
List<String> updatefieldLst= new List<String>();
MetadataService.Profile profile = (MetadataService.Profile)service.readMetadata('Profile', new String[]{'Admin'}).getRecords()[0];
//System.debug('profile--->'+profile.fullName);
for (MetadataService.ProfileFieldLevelSecurity fls: profile.fieldPermissions){
String fieldname = splitfieldname(fls.field);
if (Fieldstobeupdated.contains(fieldname)){
if (fls.editable){
updatefieldLst.add(fieldname);
}
}
//System.debug('Fully Qualified Field Name---->'+fls.field);
//System.debug('Field Name without the object Prefix-->'+fieldname);
//System.debug('Field Level security editable---->'+fls.editable);
//System.debug('Field Level security readable---->'+fls.readable);
}
for (Integer i=0; i<updatefieldLst.size(); i++){
if (i == 0){
SOQLQueryFields += updatefieldLst.get(i)+ ',';
System.debug('i==0'+i);
}
else if (i== updatefieldLst.size()-1){
SOQLQueryFields += updatefieldLst.get(i);
System.debug('i==else'+i);
}
else{
SOQLQueryFields += updatefieldLst.get(i)+ ',';
}
}
SOQLQueryFinalString = SOQLQuerySelect + SOQLQueryFields + SOQLQueryForm;
System.debug('SOQLQueryFinalString--->'+SOQLQueryFinalString);
System.debug(updatefieldLst);
//Please write the code for database query and assign it to the list
//And then update the list
}
public static MetadataService.MetadataPort createService()
{
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.endpoint_x = 'callout:ApexMetadaAPI/services/Soap/m/38.0';
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = '{!$Credential.OAuthToken}';
return service;
}
public static void refreshSessionTrick(){
String restUrl = 'callout:ApexMetadaAPI/services/data/v38.0/limits';
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(restUrl);
req.setMethod('GET');
HttpResponse res = h.send(req);
}
public static String splitfieldname(String fieldname){
String fieldnametoreturn = fieldname.substringAfter('.');
//System.debug('Splited field-->'+fieldnametoreturn);
return fieldnametoreturn;
}
}
I know I have been trying to express my views points towards the Salesforce Guru's. Please excuse me for my limited knowledge. I tried to find the solution of your requirement without hurting your expertise.
FieldPermissions
object?