Syntax Highlighter JS

Thursday, May 31, 2012

Limiting access to Visual Force pages by IP address

Sometimes you might have a need to retrieve the IP address of a user in Salesforce.   You can do this with a simple function like this:

public static String GetUserIPAddress() { string ReturnValue = ''; // True-Client-IP has the value when the request is coming via the caching integration. ReturnValue = ApexPages.currentPage().getHeaders().get('True-Client-IP'); // X-Salesforce-SIP has the value when no caching integration or via secure URL. if (ReturnValue == '' || ReturnValue == null) { ReturnValue = ApexPages.currentPage().getHeaders().get('X-Salesforce-SIP'); } // get IP address when no caching (sandbox, dev, secure urls) if (ReturnValue == '' || ReturnValue == null) { ReturnValue = ApexPages.currentPage().getHeaders().get('X-Forwarded-For'); } // get IP address from standard header if proxy in use return ReturnValue; } // GetUserIPAddress
I recommend that you put this in a utility class and then reference it as needed in code. A great use for this is to limit access to certain pages by IP address. This is accomplished by calling the method in the constructor of a visual force page controller (or controller extension) and then using the value that is returned to check against a list. Here is a very simple example that uses a hard coded dummy IP address : public MyControllerExtension (ApexPages.StandardController stdController) { // notice that the method was placed in the Util class string UserIP = Util.GetUserIPAddress(); if (UserIP != '1.2.3.4') { PageUnAuthEnabled = true; ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Unauthorized Access from: ' + UserIP)); } else { PageUnAuthEnabled = false; // insert code here for normal constructor } // check for IP address } // constructor With the constructor above in place, you can now add an outputpanel to your visual force page that only gets rendered (when for PageUnAuthEnabled == true) for unauthorized users. You could also redirect them to the unauthorized page instead.

Tuesday, May 8, 2012

Fun with links in email templates

Force.com has some really powerful email tools.  The most basic of which is the email template.  Currently, you can choose between these types of email templates:
  • Text
  • HTML (using letterhead)
  • Custom (without using letterhead)
  • Visualforce
 When you start out on the platform, you will most likely use the HTML based (with or without letterhead) templates.  The basic use case for email templates is to automatically notify a user when a new request comes in.   Of course, you will want to send the user a link to the request right?  If you look at the salesforce examples, you will see a seemingly easy way to get a link in your email - the .link field.   So for an email about a lead, you could just put {!Lead.Link} in your HTML template and be done.

Since Visualforce e-mail templates allow you to create PDF attachments, your next logical move will be to port your HTML templates to VF and create a PDF attachment (invoice, receipt, whatever).   

That is great for your external users's confirmation but what if you want to send a very similar email (including attachments) to your internal user and include a link?  That is when things get interesting. 

On a template related to a lead, you would think it would be as simple as {!RelatedTo.Link}.   You would be wrong and would get this error message:
invalid field link for sobject lead

Basically the problem is that this isn't an actual field and the visual force engine for email templates hasn't been configured to build a link in place of this logic.  You can easily confirm this by opening up force.com explorer and trying to query for the field.  When you do, you will get an error like this:
So how do you get your link into your email template?  Well you could create a formula field and hard code in your Salesforce instance but that isn't portable.  The correct way is to use some visualforce creativity to make a relative link:
<apex:outputlink value="{!LEFT($Api.Partner_Server_URL_140,FIND('.com',$Api.Partner_Server_URL_140)+4)+relatedTo.Id}">Link</apex:outputlink>

This will work brilliantly for the HTML section of your email template but in your plain text template, you want to use just the text and not the link.   So you modify the visualforce to look like this:
<apex:outputtext value="{!LEFT($Api.Partner_Server_URL_140,FIND('.com',$Api.Partner_Server_URL_140)+4)+relatedTo.Id}"/>

Now you have the text of your link in the email but unfortunately you can't insert a blank line before this link (at least as far as I know) - it will appear on the same line (at least in the preview) no matter how many blank lines you put in front of it.