9

I have a client who wants external users to submit data via a Sites VF page and update Opportunity records.

Of course the Sites profile doesn't have permissions to update standard objects. Also, the client does not want to purchase portal licenses for these external users.

I am considering two workarounds and am wondering if they are possible:

1 -- Write some Apex webservices and call them from the Sites page Visualforce controller.

Is it even possible to call your own webservices from a controller? I presume the webservices would be running in system context?

2 -- Have the Sites page create a custom object record instead, and then write a trigger to update the opp record using the custom object.

Will the trigger be running in the system context and be able to update the opp?

4 Answers 4

6

You can code the controller as without sharing and copy the values into and out of an intermediate object.

The documentation for with sharing states:

The with sharing keyword allows you to specify that the sharing rules for the current user be taken into account for a class. You have to explicitly set this keyword for the class because Apex code runs in system context. In system context, Apex code has access to all objects and fields— object permissions, field-level security, sharing rules aren’t applied for the current user.

So, by specifying without sharing the class runs in system context and has access to the Opportunity. Note that doesn't apply to the Visualforce page, itself, so you couldn't access the Opportunity directly in it via an inputField.

Example:

public without sharing class OpportunityController {
    public UsableOpp usableOpp { get; set; }

    public OpportunityController() {
        usableOpp = new UsableOpp();
    }

    public class UsableOpp {
        public String name { get; set; }
        public Decimal amount { get; set; }
    }

    public PageReference doSubmit() {
        Opportunity opp = new Opportunity();
        opp.Name = usableOpp.name;
        opp.StageName = 'Brand New';
        opp.CloseDate = Date.today();
        opp.Amount = usableOpp.amount;

        insert opp;

        return null;
    }
}

In your Visualforce:

<apex:page controller="OpportunityController">
    <apex:form >
        Name: <apex:inputText value="{!usableOpp.Name}"/><br />
        Amount: <apex:inputText value="{!usableOpp.Amount}"/><br />
        <apex:commandButton value="Submit" action="{!doSubmit}"/>
    </apex:form>
</apex:page>

You lose all benefits of the security model in Salesforce. You’ll have to manually ensure that the Opportunities are only viewable/editable by the allowed users on the site.

2
  • Yes, but I am talking about the Sites profile object permissions, not the sharing rule permissions. Unauthenticated users have read-only object permissions to standard objects. Only authenticated portal users can get edit permissions, but the client doesn't want to purchase portal licenses. wiki.developerforce.com/page/… Feb 11, 2014 at 15:33
  • @DavidCheng - I understand. Try my code and see what happens. The without sharing will definitely allow the unauthenticated sites user to create an Opportunity. Feb 11, 2014 at 15:36
1

If you work with some VF controllers, try to define them as global :

global class MySuperController
{
      //to do
}

Otherwise, you can create a custom object ("SiteOpportunity__c"), create the fields the users can update, and use a trigger on this object to update your standard opportunity. Trigger is running as system admin.

2
  • Thanks for your reply, but how would global avoid the problem of the Sites profile having read-only access to the standard objects? Feb 10, 2014 at 0:15
  • Because defining your class as 'global' or 'public without sharing' doesn't take the permission of the user in consideration. It's like using your controller as a system admin.
    – brovasi
    Feb 10, 2014 at 0:37
1

I finally made an account here just so I could post some more info on this. As David says, you can actually update standard objects with the Guest license type; despite the license restrictions. But, there is an area where the license type hurts you. If you are working on the fields at the Schema.GetDescribeFieldResult level, isUpdateable() will be false for the Guest user.

I had a loop running though all the fields of an object, and updating a found record with any new information; but it was wasn't updating anything with guest users. I was checking to ensure the field was actually updateable, hence the issue. I had to add a cut out to skip that criteria for guest users.

So I guess this is more for anyone out there looking into this and is using isUpdateable(); there is hope

2
  • | mean its expected that isUpdateable() will be false for guest user as they don't have a license. May 9, 2018 at 16:51
  • @PranayJaiswal The point of the post here is that while the field reports false for isUpdateable(), it is actually updateable by the user. So the check is not accurate. Guest Users are licensed, they have a specific license all to themselves. The isUpdateable() check is returning false solely based on license type, versus the actual CRUD permissions given to the profile/user.
    – Mock1
    May 10, 2018 at 18:32
0

I tried it but I didn't even use "without sharing". I just used "public class OnlineOrder {" and it worked. I was able to update the opp fields.

That leaves me thoroughly confused. I actually posted a question last year about system context vs. Sites profile restrictions, and I interpreted the answers to mean Sites restrictions were always in effect, regardless of the Visualforce context. (BTW Peter, you commented on this thread too.) VF controller system context versus Sites Guest User object permissions

As I read it again, I see that I misinterpreted the answers. I guess the crucial difference is in Apex vs. Visualforce components. It sounds like VF components like inputField are restricted by the profile object permissions, but the back-end Apex doing the DML is not restricted.

Anyway, thanks Peter for taking the time to work through this, and thanks brovasi also.

1
  • In your case of a simple controller the "without sharing" has the same effect as not having anything (what you did). My take is that not having the with sharing allows Apex to run in system mode as documented and apex:inputFields (VF Components) are not really Apex. It's just confusing because the user license documentation doesn't discuss things you can do in Apex. It would be clearer, for developers, if there was something on the user license breakdown about apex running in system mode, but it probably isn't the right place for it for the wider audience. Feb 12, 2014 at 1:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .