function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Sriram MSriram M 

Access and Update Contacts through Public Knowledge Website

Hi all,

I created a public knowledge website (without login) in which I have added a case creation form. Whenever I create a case through the website, it will create a contact of the user who have created that case.

If the same user tries to create a case, my code checks if the contact is already available in salesforce and appends the case to that contact. But this functionality is working only for the contacts which are created through the Website (using Guest user account).

The problem is that this functionality is not working for manually created contacts (through logged-in salesforce user account). My code doesn't even finds the contact which was manually created.

Below is my controller code.
public with sharing class CreateCaseController {
    
    public string caseIDVal = '';
    public Contact conRec{get; set;}
    public Case caseRec{get; set;}
    public String contactEmail{get; set;}
    
    List<Contact> getContactDetails;
    
    public CreateCaseController(){

        conRec = new Contact(); 
        caseRec = new Case(); 
    }
    public pagereference saveData(){
        System.Debug('======================>>>> hit inisde saveData function');
        if(conRec.lastName== null || caseRec.SuppliedCompany == null  || contactEmail == null  || caseRec.Subject == null  || caseRec.Description == null  || caseRec.Impact__c == '--What is the impact?--')
        {
            PageReference pageRef = new PageReference('/createcase');
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.ERROR,'Please fill-in all the details to create a case!');
            ApexPages.addMessage(myMsg);
            //pageRef.setRedirect(true);
            return pageRef;
        }
        else
        {
        createContactRecord();
        System.Debug('======================>>>> hit after createcontactrecord function');
        caseRec.ContactId = conRec.Id;
        if(caseRec.Impact__c == 'Just me')
        {
            caseRec.Impact__c = 'Low';
            caseRec.Urgency__c = 'Low';
            //caseRec.Case_Priority__c = '3';
        }
        else if(caseRec.Impact__c == 'Some users but not all')
        {
            caseRec.Impact__c = 'Low';
            caseRec.Urgency__c = 'Medium';
            //caseRec.Case_Priority__c = '2';
        }
        else if(caseRec.Impact__c == 'Everyone in the company')
        {
            caseRec.Impact__c = 'Low';
            caseRec.Urgency__c = 'High';
            //caseRec.Case_Priority__c = '1';
        }
        
        insert caseRec; 
        PageReference pageRef = new PageReference('/caseconfirmation?caseid='+caseRec.Id);
        pageRef.setRedirect(true);
        return pageRef;
        }
        
    }
    public void createContactRecord() 
    
    {
        System.Debug('======================>>>> hit inside createcontactrecord function');
        try
        {
           getContactDetails = [SELECT ID FROM Contact WHERE Email = :contactEmail LIMIT 1];
           System.Debug('======================>>>> hit inside createcontactrecord function try');
           if(getContactDetails.size() == 0)
           {
               conRec.Email = contactEmail;
               System.Debug('mailID doesnot exist=====>'+contactEmail);
               insert conRec;
               System.Debug('contact newly created.=====>>>>conrecid===='+conRec.Id);
           }
           else
           {
               for(Contact cntct : getContactDetails )
               {
                   System.Debug('mailID exist=====>'+contactEmail);
                   System.Debug('contactid========='+cntct.Id);
                   conRec.Id = cntct.Id;
               }
           }
            
            
            
            System.Debug('contactid='+conRec.id);
        }
        catch(System.Exception ex)
        {
            System.Debug(ex.getMessage());
        }
    }
}
the function saveData is the form submission action.

Privileges

From above privileges on profile screenshot, I could see that I don't have the 'edit' permission for contacts. But I wonder how the website is able to edit and append contacts which are created through the website but not the manual contacts.

Please help me out guys.

Thanks in advance

Best Answer chosen by Sriram M
bob_buzzardbob_buzzard
What is your org wide default for contact records?  As you are using the 'with sharing' keywords, the sharing rules will be respected and that could well stop access to contact records. One way to handle this would be to move the code that looks up the contact record to a utility method in a class declared 'without sharing' - that would give you access to all contacts in the system regardless of who owns them.  You could also change your controller to be 'without sharing', but that might present a security risk.

All Answers

bob_buzzardbob_buzzard
What is your org wide default for contact records?  As you are using the 'with sharing' keywords, the sharing rules will be respected and that could well stop access to contact records. One way to handle this would be to move the code that looks up the contact record to a utility method in a class declared 'without sharing' - that would give you access to all contacts in the system regardless of who owns them.  You could also change your controller to be 'without sharing', but that might present a security risk.
This was selected as the best answer
Sriram MSriram M
Thanks for the quick response bob.

I will give it a try using the 'without sharing' keyword as you suggested.

Since I have'nt added any pages where in the users could view any contacts anyway, how will it be a security risk?
Could you please enlighten me on that?


bob_buzzardbob_buzzard
The reason it is a security risk is that controller now has access to all records in the system that the license allows, so you need to make sure that neither you or anyone else that comes afterwards does anything that could expose data unintentionally.

Its safer to move discrete functions to a without sharing class, as the main controller then still respects sharing and the chances of inadvertent data exposure are eliminated (or much reduced anyway).
Sriram MSriram M
Thanks for the explanation Bob.

using the 'without sharing' keyword made it to work. But after adding the keyword in the code, I got an exception as below.

System.NoAccessException: The organization is not permitted to send email

Then I found that the Sandbox environment Mail Deliverability is set as 'System email only'  which was the reason that generated the exception.
I read through the SF articles and found that the Sandbox environments are set to 'System email only' in default to prevent developers from accidentally sending mails to customers.
So I changed it to 'All email' and it fixed the issue.

Once again thanks for your help Bob.