5

As I understand there are two visibility modes for Custom Settings:

  • Public settings, accessed via Setup > Custom Settings
  • Protected settings, via Grant Login Access after installing a security reviewed package

The latter is great for hiding your dirty post-install laundry from package users. Or for using settings as invisible tables to hold generated data (like countries and states) that can't be messed with.

But it seems with Protected Custom Settings, there is no way to administer them in BETA.

If there is no License record and hence no Login Access, how can the settings be administered through the native user interface?

  • 2
    I went through the same thing. I could not find a way to do it either. I know you know this but I just used public custom settings and will refactor (comment out code, delete, recreated as private, yada, yada, yada) them to private once ready to go. Make more work but it was the only way I could find. Thank you for the question, I hope someone has a clear answer – Eric May 24 '14 at 0:40
  • Yeah, this is one of a few things that make beta packages a pain IMO. Not being able to upgrade is another, especially when you're trying to work with post-install scripts! – Matt Lacey May 24 '14 at 2:25
  • @LaceySnr what options are there for alternate, more desirable behaviour? That Protected settings just behave as Public ones when part of a Beta install? – bigassforce May 24 '14 at 2:35
  • 2
    I'd prefer some kind of beta license. The idea of beta software is to test things that could go to production, can't really test accurately when the behaviour is different. – Matt Lacey May 24 '14 at 2:37
1

Here's a suggestion that may be of use to you that's based on the classic test helper class such as the one below which contains a few snippets of one I used recently for an org I was working in. I'll explain some suggested modifications at the end.

/**
 * A collection of utilities and methods for use in unit tests.
 * @author crmprogdev
 */

@isTest(seeAllData=true)
global class XXXX_Test_Helper_Util {

global PrimAdmin_CustSttng__c Admin {set;}
global PrimAdmin_CustSttng__c Admin1 {set;}
global TBA_CustSttng__c TBA {set;}
global EHcc_CustSttng__c CC1 {set;}
global Pub_Boolean_A__c BoolA {get;}
global Pub_Bool_B__c BoolB {get;} 

global static void init() {
    /* create our global settings object and set the defaults */


    PrimAdmin_CustSttng__c Admin = generateTestPrimAdmin();
    PrimAdmin_CustSttng__c Admin1 = generateTestPrimAdmin1();
    EHcc_CustSttng__c CC1 = generateTestCC1();

    User TBA_u = generateTBA();

    TBA_CustSttng__c TBA = generateTestTBA(TBA_u); 

}

/** a default user to use in System.runAs() */
private static User testRunner {
    get {
        if (null == testRunner) {
            // all test code should execute under a user we can control so as to avoid
            // surprises when deploying to different environments.
            UserRole[] roles = [SELECT Id FROM UserRole WHERE DeveloperName = 'Admin'];
            if (roles.isEmpty() == true) {
                roles.add(new UserRole(DeveloperName = 'Admin', Name = 'r0'));
                insert roles;
            }

            testRunner = new User(Alias = 'tstr01', Email='tstr01@kube.com', EmailEncodingKey='UTF-8', FirstName= 'TstrFrst', LastName='TstrLst01', LanguageLocaleKey='en_US', LocaleSidKey='en_US', TimeZoneSidKey='America/Los_Angeles', UserName='tstt01@xxx.com');
            testRunner.UserRoleId = roles[0].Id;
            insert testRunner;
        }

        return testRunner;
    }

    private set;
}

global static PrimAdmin_CustSttng__c generateTestPrimAdmin(){
        PrimAdmin_CustSttng__c Admin = new PrimAdmin_CustSttng__c();
        if (PrimAdmin_CustSttng__c.getValues('Admin') == null){

            Admin.ContactName__c = 'Carey XXXX' ;
            Admin.UserID__c = 'xxxxxxxxxx'; //(sandbox, prod)
            Admin.UserName__c = 'support@xxxx.com';
            Admin.Email__c = 'support@xxxx.com';    // support@xxx.com.xxxxsandb    
            Admin.Name = 'Admin';
            upsert Admin;

        }               
        else if (PrimAdmin_CustSttng__c.getValues('Admin') != null ){ 
            Admin = PrimAdmin_CustSttng__c.getValues('Admin');

        }

        return Admin;
}

global static PrimAdmin_CustSttng__c generateTestPrimAdmin1(){
        PrimAdmin_CustSttng__c Admin1 = new PrimAdmin_CustSttng__c();
        if (PrimAdmin_CustSttng__c.getValues('Admin1') == null){
            Admin1.ContactName__c = 'Steven XXXXX';
            Admin1.UserID__c = xxxxxxxxxx; //(sandbox, prod)
            Admin1.UserName__c = 'xxxxxxxxxx@gmail.com';
            Admin1.Email__c = 'stevenjxxxxxx@gmail.com';        
            Admin1.Name = 'Admin1';
            upsert Admin1;

        }               
        else if (PrimAdmin_CustSttng__c.getValues('Admin1') != null ){ 
            Admin1 = PrimAdmin_CustSttng__c.getValues('Admin1');

        }
        return Admin1;
}



global static EHcc_CustSttng__c generateTestCC1(){
        EHcc_CustSttng__c CC1 = new EHcc_CustSttng__c();
        if (EHcc_CustSttng__c.getValues('CC1') == null){
            CC1.Name = 'CC1';
            CC1.SendCC__c = true;
            upsert CC1;


        }
        else if (EHcc_CustSttng__c.getValues('CC1') != null ){ 
            CC1 = EHcc_CustSttng__c.getValues('CC1');

        }
        return CC1;
}


global static User generateTBA(){

    User U0 = [SELECT Id, Name, email, Division, Title, UserRoleId, ProfileId, Username FROM User WHERE IsActive = True AND (Profile.DeveloperNameId = 'Admin' OR Profile.Id = 'FloridaAdmin') limit 1];
    User U1 = [SELECT Id, Name, email, Division, Title, UserRoleId, ProfileId, Username FROM User WHERE IsActive = True AND (Profile.DeveloperNameId = 'SalesManager' OR Profile.Id = 'FloridaSalesManager') AND UserRole.Name = 'Project Manager' limit 1];
    list<Account> TBAa = new list<Account>(); // TBA contact list
    list<Id> TBAasrId = new list<Id>(); // TBAa insert results validation list
    list<Contact> TBAc = new list<Contact>(); // TBA contact list
    list<Id> TBAcsrId = new list<Id>(); // TBAc insert results validation list
    list<User> TBAu = new list<User>(); // TBA user list
    list<Id> TBAusrId = new list<Id>(); // TBAu insert results validation list

    if(U0.Id == null ){ 
        TBAu[0] = null; 

    } else 
    system.RunAs(U0){

    /* create the TBA acct */

    Account tbaact = new Account(Name = 'TBAact', Is_Active__c = true, Region__c = 'SouthEast', OwnerID = U1.Id  );

    TBAa.add(tbaact);

    /* insert the new Accts */

    if(TBAa.IsEmpty() == false)Insert TBAa;

        /* Create the TBA contact */

    Contact tbaCtc = new Contact( AccountID = TBAa[0].Id, LastName = 'TBAtst1', Phone = '777-755-0001', MailingStreet = '999 TBD St', MailingCity = 'TBA', MailingState = 'FL', Position__c = 'Ambassador', MobilePhone = '777-755-1001', RecordTypeId = '012400000005IeZAAU' );

    TBAc.add(tbaCtc);

    /* insert the tbaCtc */

    if(TBAc.IsEmpty() == false) Insert(TBAc);

    /* create the TBA user */

    User tbaUsr = new User(ContactID = TBAc[0].Id, Alias = 'tbatst1', Email='tbatst1@xxxxtst.com', EmailEncodingKey='UTF-8', LastName= TBAc[0].LastName, LanguageLocaleKey='en_US', LocaleSidKey='en_US', ProfileId = U5.ProfileId, MobilePhone = TBAc[0].MobilePhone, Phone = TBAc[0].Phone,TimeZoneSidKey='America/Los_Angeles', UserName='tbatst1@xxtst.com');

    TBAu.add(tbaUsr);

    if(TBAu.IsEmpty() == false) Insert TBAu;

    TBA_CustSttng__c TBA2 = new TBA_CustSttng__c();
    TBA2 = Kube_Test_Helper_Util.generateTestTBA(TBAu[0]);
    }           
    return TBAu[0];
}   


public static TBA_CustSttng__c generateTestTBA(User TBA_u){

    User TBAu = TBA_u;
    TBA_CustSttng__c TBA1 = new TBA_CustSttng__c ();
    if(null == TBA1){
    TBA1.ContactID__c = TBAu.ContactId; 
    TBA1.ContactName__c = 'TBAtst1'; 
    TBA1.CtcRecTypeID__c = '012400000005IeZAAU'; 
    TBA1.UserID__c = TBAu.Id;
    TBA1.UserName__c = TBAu.UserName;
    TBA1.UserProfileID__c = TBAu.ProfileId;
    TBA1.Email__c = TBAu.Email ;
    TBA1.Name = 'TBA1';
    upsert TBA1;
    }
    return TBA1;

    }
}

You'll notice I've included a number of custom settings in the above. The custom settings that I'd want to be private would be:

PrimAdmin_CustSttng__c Admin {set;}
PrimAdmin_CustSttng__c Admin1 {set;}
TBA_CustSttng__c TBA {set;}

All of the above contain information about UserID's, email addresses, etc that you don't want to be visible to anyone else.

The custom settings to be set as public would be:

    global EHcc_CustSttng__c CC1 {set;}
global Pub_Boolean_A__c BoolA {get;}
global Pub_Bool_B__c BoolB {get;} 

The first one simply is used to set whether or not a CC is sent with an error handler message. The latter two are booleans that I've added for the purpose of answering this post. By using a strategy of setting Booleans in a Public Custom Setting, values could presumably be changed if the Boolean were set to True. So by altering the above code as below, I believe something like this could potentially work as a solution:

global static PrimAdmin_CustSttng__c generateTestPrimAdmin(){
        PrimAdmin_CustSttng__c Admin = new PrimAdmin_CustSttng__c();
        if (Pub_Boolean_A__c.getValues('BoolA') != null && BoolA.Value == 'true'){

            Admin.ContactName__c = BoolA.ContactName__c ;
            Admin.UserID__c = BoolA.UserID__c
            Admin.UserName__c = BoolA.UserName__c;
            Admin.Email__c = BoolA.Email__c;    // support@xxx.com.xxxxsandb    
            Admin.Name = BoolA.Name;
            upsert Admin;

        }               
        else if (Pub_Boolean_A__c.getValues('BoolA') == null || BoolA.Value == 'false'){

            Admin.ContactName__c = 'Carey XXXX' ;
            Admin.UserID__c = 'xxxxxxxxxx'; //(sandbox, prod)
            Admin.UserName__c = 'support@xxxx.com';
            Admin.Email__c = 'support@xxxx.com';    // support@xxx.com.xxxxsandb    
            Admin.Name = 'Admin';
            upsert Admin;

        }               
        else if (PrimAdmin_CustSttng__c.getValues('Admin') != null ){ 
            Admin = PrimAdmin_CustSttng__c.getValues('Admin');

        }

        return Admin;
} 

It would seem to me that using this type of approach would allow a developer of managed packages to have their private custom settings, yet also all them to "edit" them using public custom settings during development.

Note: I have not tested this, instead only taking the time to collect some snippets of code and modify them "on the fly" to present the concept for consideration. I do not develop "officially" managed packages as yet but can see where this approach would seem likely to prove fruitful. Obviously the runAs user in the code I presented would not be necessary. I included it to illustrate the source and context of the original code.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.