I've been testing out a component where one can programmatically create a field in the user object. It's being used to allow a user to check a few boxes that'll filter components in pages (using the lightning page component filtering) that is unique to that user.
With this test I've met an annoying problem. If I manually create the field, it's all good because we get to decide the field level access. But when I create it programmatically it comes with zero access to any users even my own (sys admin).
The way I'm creating the field is:
global with sharing class FieldGen {
//@future(callout = true)
global static void makeCreateUserFieldCallout(String intendedName){
String objectapiname = 'User';
/* assertFieldName just makes name acceptable for the API name of the field. */
String fieldapiname = TogglerCtrlApex.assertFieldName(intendedName, true);
String fieldlabel = TogglerCtrlApex.assertFieldName(intendedName, false);
String fielddescription = 'Field created for topic visibility toggler component!';
try{
HttpRequest requestinside = new HttpRequest();
requestinside.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
requestinside.setHeader('Content-Type', 'application/json');
requestinside.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v26.0/tooling/sobjects/CustomField/');
requestinside.setMethod('POST');
String fieldDef = '{"Metadata" : ';
String metadef = '"type" : "Checkbox","description" : "'+fielddescription+'","defaultValue":"true", "inlineHelpText" : "","precision" : null,"label" : "'+fieldlabel+'","required" : false';
fieldDef += '{'+metadef+'},';
fieldDef += '"FullName" : "'+objectapiname+'.'+fieldapiname+'"}';
system.debug(fieldDef);
requestinside.setBody(fieldDef);
Http http = new Http();
HTTPResponse res = http.send(requestinside);
System.debug(res.getBody());
}
catch(Exception e){
System.debug(e.getMessage());
}
}
}
Basically using the API to create a field in the User Object. Unfortunatelly it doesn't give access though =/
I've been experimenting with the MetadataService class to try to add field permissions to a permission set when the field is created. This isn't working though and the documentation for this class is very slim. This is what I have so far:
public with sharing class MetadataServiceExamples
{
@future(callout = true)
public static void testPerm()
{
/* Find the Quick Toggler Permission Set! */
MetadataService.MetadataPort service = createService();
String[] permissionSetNames = new String[] {'Quick_Visibility_Toggler_Permissions'};
List<MetadataService.PermissionSet> perm =
(List<MetadataService.PermissionSet>) service.readMetadata('PermissionSet', permissionSetNames).getRecords();
MetadataService.PermissionSet quickPerm = perm.get(0);
System.debug('Test: ' + quickPerm.fieldPermissions);
MetadataService.PermissionSetFieldPermissions fieldSec = new MetadataService.PermissionSetFieldPermissions();
fieldSec.field='User.TestFieldA__c';
fieldSec.editable=true;
fieldSec.readable=true;
quickPerm.fieldPermissions.add(fieldSec);// = new MetadataService.PermissionSetFieldPermissions[] {fieldSec} ;
System.debug('Test: ' + quickPerm.fieldPermissions);
List<MetadataService.SaveResult> results =
service.updateMetadata(
new MetadataService.Metadata[] { quickPerm });
System.debug('Results: ' + results);
//handleSaveResults(results[0]);
}
}
It seems I can't access and change the permission set though. WIth that being said, does anyone know of a way I could either add CRUD permissions for the new field to a permission set or a profile programmatically right after the field is created?
EDIT:
Based on the best answer I just added this method to the class and it adds permissions to a permission set:
@AuraEnabled
public static void addToPermissionSet(String fieldName){
String fieldAPIName = assertFieldName(fieldName, true); /* this just makes sure theres's an __c in the input. */
/* Get Id of permission Set and build API name of field. */
PermissionSet ps = [SELECT Id,Name FROM PermissionSet WHERE Name = 'Example' LIMIT 1];
String fullAPIName = 'User.'+fieldAPIName; /* Example: User.TestMe__c */
System.debug('FullAPI:' + fullAPIName);
FieldPermissions newPerm = new FieldPermissions();
newPerm.Field = fullAPIName;
newPerm.ParentId = ps.Id;
newPerm.PermissionsEdit = true;
newPerm.PermissionsRead = true;
newPerm.SobjectType = 'User';
Insert newPerm;
}