Firewalls and Proxies – Technical Architect Series

Standard

What is a Firewall?
In simple words, a firewall is something (software or hardware) which protects your resources from external world (internet).

Why Firewall?
Ask yourself these questions:
Do you leave your bank lockers unlocked?
Do you leave your car unlocked in the parking lot?
If your answer is in negative (unless you are adventurous) then, why would you want to expose your servers to the internet?
You would want to put some security to protect your server’s resources from public/internet. And at times you may want to restrict your employees from accessing certain websites. You can do that by using a Firewall.

How does a Firewall work?
Firewall works, based on pre-defined set of rules, typically done by Network Admins. These rules are instructions given to a Firewall. Based on these instructions Firewall will allow or deny access to resources.

Are TAs expected to setup a firewall?
Nope, they are not. 9 out of 10 times your customer’s Network Admins would already set this up for you. But as a TA, you are expected to understand how Firewall works. TAs are expected to co-ordinate with Network Admins to setup the Firewall rules to gain access to resources on the servers.

Why will a TA even bother about Firewall, if it’s already setup by customer’s network admins?
Well, many a times when you try to connect to an external client system from salesforce. You may hit client’s network firewall. The firewall may not allow a callout/request from Salesforce to reach client’s system. It’s because firewall doesn’t recognizes the request as a valid one. Hence you will have to instruct firewall to allow requests coming from salesforce. Meaning a new rule should be added to firewall’s rule set, where your client’s team may ask you to provide IP ranges of Salesforce’s data centers.

What is a Proxy?
In simple words, a proxy is like a middleman between two parties (systems). A proxy could be software application or a hardware device or a mix of both.

For example, if you are unable to access internet from your browser. You will go to internet options and try to check your network settings and see if your proxy setting is set properly. If you correct your proxy setting then your internet starts working. Which means if you typed google.com in the address bar and hit enter key, your request will first go to your proxy (its like you are asking your proxy to get you google.com), proxy will forward your request, get the response and send it back to your browser.

What is a Forward Proxy?
A forward proxy controls and monitors traffic from an application behind a firewall.

What is a Reverse Proxy?
A reverse proxy controls and monitors traffic from the internet that requires access to a server inside the customer’s firewall (a typical use case when working with Salesforce.com and external systems)

What are some of the Reverse Proxy use cases, from a salesforce.com implementation standpoint?
Your client might open up following services to salesforce.com via a Reverse Proxy.

  • Delegated Authentication Endpoint
  • Web services (REST or SOAP)
  • Outbound Message Endpoint
  • Email Relay

So whenever you try to hit any of the above services, your request will first land on the client’s Reverse Proxy server. And it is Reverse Proxy server’s responsibility to forward your request to appropriate services.

Here are some of the famous technologies used by enterprises. There are many more such technologies available in the market.

  • IBM DataPower
  • Layer 7 Secure Span Gateway
  • Apache Http Server – moc_proxy

What is a Proxy rule?
Proxy servers allow the admins to define a set of rules. These rules can include following (but not limited to)

  • Authentication
  • Control time of access
  • URL Filtering
    for example google.com may be allowed but bet365.com may be blocked.
  • etc….

Hope that’s helpful.

Watch out for more blog post on this TA series.

Advertisements

Where is the Accept button, for Lead list?

Standard

Recently someone asked me how to get Accept button for Lead/Case, on list view?

The answer could be simple. But point here is, not everyone knows that Accept button is treated differently from other standard buttons. And hence, many of the seasoned professionals too struggle to get it right first time.

People often wonder, “I have checked Accept button in the list view layout but why is Accept button still not appearing on List view?”

Standard Accept Button Checked

Well, the answer is Queues.
Just go and create a Queue for Lead/Case and Accept button will start appearing on the list view screen.

So, here are some of the steps for getting Accept button visible on list views.

Step 1: Create Queue

Create a Queue for Lead

Step 2: Go to list view
You will notice that your newly created Lead Queue appears in the list view dropdown and when selected, the Accept button is visible.

Lead Queue list view

Hope that’s helpful

Sorting, Pagination in Visualforce using DataTables JQuery plug-in.

Standard

datatables in vf

What is this DataTables.net?
DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, which will add advanced interaction controls to any HTML table.

My Attempt
I did little bit of dotnet programming in my early days. I remember using ado.net controls for binding data to a list on an aspx page with just drag and drop. It was exciting to be able to pass SQL statements to controls directly in design time.

I always wondered if Salesforce would introduce similar VF components. For good or bad, that didn’t happen. However, Salesforce did a better thing by introducing VF components. Encouraging developers to create their our own VF components and reuse them just like you do in dotnet or java world.

Here is my attempt to create a VF component, which can take SOQL query, List of fields and Headers in design time.

I tried keep the code simple, you may tweak it as needed.

Here is the code…enjoy..!

VF Page

<apex:page docType="html-4.01-strict">
    <c:quickTableComp cContainerId="testtable"
        columnFields="Id, Name, AccountNumber"
        columnTitles="Record ID, Account Name, Account Number"
        soql="select Id, Name, AccountNumber from Account"    
    />
</apex:page>

VF Component

<apex:component controller="quickTableHandler">
    <apex:attribute name="cContainerId" type="String" required="true"  description="Id of the container which will hold & display the table" assignTo="{!cContainerId}"  />
    <apex:attribute name="soql" assignTo="{!soql}" type="String" description="SOQL query to execute and populate records." />
    <apex:attribute name="columnFields" assignTo="{!columnFields}" type="String" description="Comma-separated list of fields to display." />
    <apex:attribute name="columnTitles" assignTo="{!columnTitles}" type="String" description="Comma-separated list of column titles." />

    <link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.0/css/jquery.dataTables.css"/>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="http://cdn.datatables.net/1.10.0/js/jquery.dataTables.js"></script>
    
    <script type="text/javascript">
            $(document).ready( function() {
                $('#{!cContainerId}').dataTable();
            } );
    </script>        

    <div class="full_width">
                
        <table cellpadding="0" cellspacing="0" border="0" class="display" id="{!cContainerId}" style="width:980px">
            <thead>
                <apex:outputPanel layout="none">
                    <tr>
                        <apex:repeat value="{!columnTitlesList}" var="t">
                            <th>
                                <apex:outputText value="{!t}" />
                            </th>                   
                        </apex:repeat>
                    </tr>
                </apex:outputPanel>
            </thead>
            <tbody>
                <apex:repeat value="{!records}" var="r">
                    <tr>
                        <apex:repeat value="{!columnFieldsList}" var="f">
                            <td>
                                <apex:outputField value="{!r[f]}" />
                            </td>
                        </apex:repeat>
                    </tr>
                </apex:repeat>
            </tbody>
        </table>
    </div>    

</apex:component>

Apex Class

public with sharing class quickTableHandler {

    public String columnFields { get; set; }
    public String soql { get; set; }
    public String columnTitles { get; set; }

    public List<String> columnFieldsList {
        get {
            if(columnFieldsList == null && columnFields != null) {
                columnFieldsList = columnFields.split(',');
                for(Integer x = 0; x < columnFieldsList.size(); x++) {
                    columnFieldsList[x] = columnFieldsList[x].trim();
                }
            }
            return columnFieldsList;
        }
        set;
    }
    
    public List<String> columnTitlesList {
        get {
            if(columnTitlesList == null && columnTitles != null) {
                columnTitlesList = columnTitles.split(',');
                for(Integer x = 0; x < columnTitlesList.size(); x++) {
                    columnTitlesList[x] = columnTitlesList[x].trim();
                }
            }
            return columnTitlesList;
        }
        set;
    }

    public List<sObject> records {
        get {
            if(records == null && soql != null) {
                records = Database.query(soql);
            }
            return records;
        }
        set;
    }
}

How to find out, if custom fields are referenced in your code? by using Apex & VF

Standard

How to find out, if custom fields are referenced in your code?

There could be many ways of doing it. Some common ones I keep hearing are:

  • Try deleting a field from salesforce ui, you will know if its referenced anywhere?
  • Do a text search across your code from eclipse ide.
  • etc…

Well, here is my attempt. I will take help of Apex and Visual Force to answer above question.

Many of us may or may not be aware that salesforce provides few important standard objects like:

  • ApexClass
  • ApexPage
  • ApexComponent
  • ApexTrigger

You might be thinking, when do we use these objects? what are the use cases? well, that’s what this blog post attempts to do. To get you start thinking in this direction.

I used little vf and couple of classes to perform a text search across code and tell you if a custom field is referenced anywhere in your code. I tried keeping the code simple, you may tweak it as needed.

So here goes the code..enjoy..!

fields used

VF Page


<apex:page controller="SmartWays" >
 <apex:form >
 <apex:SelectList value="{!selectedObject}" size="1" onchange="initFieldsScript()">
 <apex:selectOptions value="{!Objects}"></apex:selectOptions>
 <apex:actionFunction action="{!initFields}" name="initFieldsScript" rerender="pbtFields">
 </apex:actionFunction>
 </apex:SelectList>
 <apex:pageBlock >
 <apex:pageblocktable value="{!lstFieldResult}" var="field" id="pbtFields">
 <apex:column headervalue="Field Name">{!field.FieldApiName}</apex:column>
 <apex:column headervalue="Is Used">{!field.IsUsed}</apex:column>
 </apex:pageblocktable></apex:pageBlock>
 </apex:form>
 </apex:page>

Apex Class


public class SmartWays{

public String selectedObject {set; get;}
 private List<ApexClass>     lstClasses = new List<ApexClass>();
 private List<ApexComponent> lstComponent = new List<ApexComponent>();
 private List<ApexPage>         lstPage = new List<ApexPage>();
 private List<ApexTrigger>     lstTrigger = new List<ApexTrigger>();
 Map<String, Schema.SObjectType> mapObjects = Schema.getGlobalDescribe();
 public List<FieldsWrapper> lstFieldResult {get; set;}

public SmartWays(){
 lstClasses = [select Name, Body from ApexClass];
 lstPage = [select Name, Markup from ApexPage];
 lstComponent = [select Name, Markup from ApexComponent];
 lstTrigger = [select Name, Body from ApexTrigger];
 selectedObject = '';
 }

public List<SelectOption> getObjects(){
 List<String> sortThis = new List<String>();

List<Schema.SObjectType> gd = mapObjects.Values();
 Set<String> lstKeys = mapObjects.keySet();
 sortThis.addAll(lstKeys);
 sortThis.sort();

List<SelectOption> options = new List<SelectOption>();
 for(String s : sortThis){
 options.add(new SelectOption(s,s));
 }

return options;
 }

public PageReference initFields(){
 lstFieldResult = new List<FieldsWrapper>();
 if(mapObjects.containskey(selectedObject)){
 Schema.SObjectType s = mapObjects.get(selectedObject);
 Schema.DescribeSObjectResult r = s.getDescribe();

Map<String, Schema.SObjectField> fields = r.fields.getMap() ;
 Set<String> fieldnames = fields.keySet();
 List<String> fieldList = new List<String>();
 fieldList.addAll(fieldNames);
 fieldList.sort();
 String fName = '';
 for(integer i=0; i<fieldList.size(); i++){
 fName = fieldList[i];
 if(fName.endswith('__c')){ //only include the custom fields
 FieldsWrapper field = new FieldsWrapper();
 field.FieldApiName = fName;
 field.isUsed = hasReferences(fName);
 lstFieldResult.add(field);
 }
 }
 }
 return null;
 }

private boolean hasReferences(string fieldName){
 Boolean bRet = false;
 for(ApexClass cls:lstClasses){
 if(cls.body.contains(fieldName)){
 bRet = true;
 break;
 }
 }

if(!bRet){
 for(ApexPage pg:lstPage){
 if(pg.Markup.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

if(!bRet){
 for(ApexTrigger trg:lstTrigger){
 if(trg.Body.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

if(!bRet){
 for(ApexComponent com:lstComponent){
 if(com.Markup.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

return bRet;
 }

public class FieldsWrapper{
 public string FieldApiName {set; get;}
 public string FieldLabel {set; get;}
 public boolean isUsed {set; get;}
 }

}

Hope that’s helpful

Get your Visitor’s IP address via sites

Standard

Have you ever ran into a situation, where you need to figure out your site’s visitor’s IP address? Well, many of us may or may not have. But the fact is, while working with sites, sooner or later you will bump into this requirement.

So, like every requirement, even this one can be dealt with, in many different ways. Like

1. Use an existing program like http://jsonip.com or http://jsonip.appspot.com/
2. Write a program (which will return visitor ip) in your choice of language (like php, asp, jsp, etc..) and put it on a web server.
3. Create a public vf page and use apex in the background, to get your visitor’s ip address.

I wouldn’t suggest option # 1 and 2 as they may or may not be available when your visitors come to your site. But if you go with option 3
then its almost certain that your visitor ip address can be traced. Because both your site and ip tracing vf page will be on sfdc servers. So, if a visitor is able to see your site that mean you can trace their ip address, for sure.

Here is the sample code:

VF page: getip


<apex:page controller="getipController" showheader="false" contenttype="application/json">{!ipAddress}</apex:page>

 

Apex class getipController


public class getipController {
 public String ipAddress {get; set;}
 public getipController(){
 ipAddress = ApexPages.currentPage().getHeaders().get('X-Salesforce-SIP');
 }
 }

 

Now that you can have code in place. Go ahead and make this page public from your force.com site.

That’s it. Your ip tracing page is now ready to be used in your site.

Using jQuery, you could make a JSON call:




$.getJSON("your page url", function(data){alert(data);});



 

Hope that’s helpful.

Dynamic SOQL with conditions

Standard

Very often, salesforce developers work on requirements where they have to generate SOQL queries on the fly/dynamically. And everyone has there own style of coding, hence they attempt this topic in their own unique ways.

Here is the code snippet I generally use when working with dynamic SOQL. Hope thats helpful 🙂

private String strSOQL = '';

private void prepareSOQL(){
 strSOQL = 'Select Name, Ticker_symbol__c, Headquarters__c, Company_Type__c, Ownership__c from CustomObject__c';
 List<string> conditions = new List<string>();

if(acct.Name!=''){
 conditions.add('Name LIKE \'%' + acct.Name + '%\' ');
 }

if(acct.Ticker_symbol__c!=''){
 conditions.add('Ticker_symbol__c LIKE \'%' + acct.Ticker_symbol__c + '%\' ');
 }

if(acct.Industry__c!=''){
 conditions.add('Industry__c = \'' + acct.Industry__c + '\' ');
 }

if(acct.Company_type__c!=''){
 conditions.add('Company_type__c = \'' + acct.Company_type__c + '\' ');
 }

if(acct.Company_status__c!=''){
 conditions.add('Company_status__c = \'' + acct.Company_status__c + '\' ');
 }

if (conditions.size() > 0) {
 strSOQL += ' WHERE ' + conditions[0];
 for (Integer i = 1; i < conditions.size(); i++)
 strSOQL += 'AND ' + conditions[i];
 }
 }