Sunday 11 October 2015

Write your first BOOTSTRAP

BOOTSTRAP is famous for its fast and easier web development, so we should start designing our page using this.

BOOTSTRAP has multiple advantages:

  • Easier to implement
  • More responsive UI
  • Mobile compatible UI
  • Open source
  • HTML syntax
  • And the list goes on
Now let's learn how to include BOOTSTRAP framework in VF pages, which will help us to design a   responsive UI in Salesforce.

Few things to know before we proceed to VF coding:
  • BOOTSTRAP and jQuery Library must be included in page
  • All the BOOTSTRAP codes should be written inside Container-Fluid or Container class
  • It is always advisible to include META tags within the Bootstrap page for encoding, width scale and IE compatibility.
  • All the Bootstrap flavour on the page comes with the Class property of HTML elements, we just need to write the class value of the component and it will work as expected.
  • Remembering Bootstrap is also very easy, because the component names are exactly same what  they do. For ex: row creates a row, col creates a column, panel creates a panel etc..
Few properties which is very common and we will be using it in the example:
  • DIV: This will be used mostly to design the page, with different types of classes attached to it.
  • ROW: This creates a row in the page for parent element or divides the page in rows
  • COL-XX-YY: This creates the column for the row or divides the parent element area in columns. XX is the screen size of the machine and the possible values would be LG(Large), MD(Medium), SM(Small), XS(Extra Small). YY is the column size according to the page or parent element area, max size would be 12 and minimum could be 1. So the complete page can be divided into 12 parts.
  • PANEL: This creates a Panel in the page, which can further contain Header, Body and Footer.
  • BTN: This crates the button in the page.
Few styling of Bootstrap element, we can use few predefined attribute along with the class name:
  • DEFAULT(Grey color)
  • PRIMARY(Blue color)
  • SUCCESS(Green color)
  • INFO(Light Blue color)
  • WARNING(Orange color)
  • DANGER(Red color)
Above styling properties is always used with some class name, like panel-default, btw-primary etc..

Below is a very basic VF page of a login screen, but it will give you an idea how to go ahead with BOOTSTRAP.

VF Page:

<!--In below apex:page tag, I have disabled all the CSS property so that we get on boostrap flavour in our page. And also I have used a custom controller for the page-->

<apex:page id="loginFlow" showHeader="false" sidebar="false" standardStylesheets="false" applyBodyTag="false" applyHtmlTag="false" controller="CustomLogin">

<html>
    <head>
        <title>AK Computing</title>
        <!-- below is for character encoding -->
        <meta charset="utf-8" />
        <!-- below is to make the page IE compatible -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <!-- below is make the page responsive according to the screen size -->
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <!-- These three libraries are the pre-requisite for Bootstrap -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
        <style>
            .blackBackground{
                background-color: #000000 !important; 
            } 
            .commandButton{
                background-color: #337ab7 !important;
                border-color: #2e6da4 !important;
                color:#EEEEEE;
                width:100% !important:
            }
            .inputTxt{
                width:35%;
                margin-bottom:2%;
            }
            .mainPanel{
                min-height:200px;
                margin-left:30%;
                margin-right:30%;
                margin-top:20%;
                margin-bottom:20%; 
            } 
        </style>
        <script></script>
    </head>
    <body class="blackBackground">
        <apex:Form >
            <!--below tag contains all the bootstrap -->
            <div class="container-fluid">
                <!--below creates a panel of type default, but here I have customised it with css -->
                <div class="panel panel-default mainPanel">
                    <div class="panel-body">
                        <!-- row divides the pages or parent element area into rows, here i have divided Panel into three parts -->
                        <div class="row"> 
                            &nbsp; 
                        </div>
                        <div class="row">
                            <!-- col creates the column, here it will take the complete width as I have mentioned 12 in the size -->           
                            <div class="col-xs-12">
                                <center>
                                    <div class="row">
                                        <apex:inputText value="{!userName}" id="userNameInput" 
                                            html-placeholder="Username" styleClass="inputTxt"/>
                                    </div>
                                    <div class="row">
                                        <apex:inputSecret value="{!password}" id="passwordInput" 
                                            html-placeholder="Password" styleClass="inputTxt" />
                                    </div>
                                    <div class="row">
                                        <apex:outputPanel rendered="{!error}">
                                            <apex:outputText ><Font color="red">{!errorMessage}</font></apex:outputText>
                                        </apex:outputPanel>
                                    </div>
                                    <div class="row">
                                        <apex:commandButton action="{!login}" id="commandBtn" styleClass="commandButton"
                                            style="width:35%;" value="{!$Label.site.login_button}" />
                                    </div>
                                    <div class="row">
                                        &nbsp; 
                                    </div>
                                    <div class="row">
                                        <apex:outputLink value="{!$Page.CustomForgotPassword}"> {!$Label.site.forgot_your_password_q}
                                        </apex:outputLink>
                                    </div>
                                </center>
                            </div>
                        </div>
                        <div class="row"> 
                            &nbsp; 
                        </div>
                    </div>
                </div>
            </div>
        </apex:Form>
    </body>
</html>
</apex:page>


There is quite a long list of Bootstrap predefined classes which makes life easier for the designer, I hope this will give you a hint how to start with Bootstrap.

Decrypt complete document in Salesforce

In my previous post I have written how to Encrypt a document, so here it is how to decrypt a document.

There are two ways to do it:

  1. Without storing the decrypted document on cloud
  2. Store it in decrypted form as an attachment.
Below are the codes for both of the things:

APEX:

//Using future method here to avoid CPU time limit exception

// Below method do not store anything on cloud and sends email with decrypted document to an 
// email Id

@future
public static void sendDecryptedAtt(String accId,Blob key, String emailId)
{

    List<Attachment> attList=[Select id,name,body from Attachment where parentId=:accId limit 1];


    if(attList.size() > 0){
        Blob decrypted = Crypto.decryptWithManagedIV('AES256', key, attList[0].body);
 
        String blobString=decrypted.toString();

        Blob doc=EncodingUtil.base64decode(blobString);
        String fileName=accAtt.name;

        sendEmail(doc,emailId,fileName);

        createAtt(doc, fileName, accId);
    }    
}

// below method sends email to the given email address
Public Static Void sendEmail(Blob attachmentFile, String emailId,String fileName)
{
    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    efa.setFileName(fileName);
    efa.setBody(attachmentFile);

    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    email.setSubject('Decrypted File: '+ fileName);
    String[] emails=new List<String> {emailId};
    email.setToAddresses( emails);
    email.setPlainTextBody('Hi,\n\nPlease find attached decrypted document.\n\nThanks');

    email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

    // Sends the email
    Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[ {email});
}


//Below method creates an attachment in the Salesforce with decrypted content
Public Static Void createAtt(Blob attachmentFile, String fileName, String accId)){
    Attachment att=new Attachment();
    att.name = 'Decrypted_'+fileName;
    att.body = attachmentFile;
    att.parentId = accId;

    insert att; 
}

Above code works for all kind of documents. Encryption technique is present in my previous posts.

Encrypt Complete Document in Salesforce

In multiple business scenario it is required to encrypt the document which are restricted in nature, the reason is since Salesforce is a on cloud application so there could be a policy of a company to not to store documents on cloud without encrypting it.

Salesforce do provide encrypted fields to store the data securely but do not provide any standard functionality to encrypt a complete document, but I was able to encrypt the complete document successfully using custom logic.  Although I had done it two years back but now making available for everyone.

Salesforce supports multiple encryption algorithm, here I am going to use AES256 for encryption.

For encryption key, I have used Protected Custom Setting as this is a most secured place to store the data.

Please note this code can be used for any document type.

Below is the example with end to end code to encrypt a document and attach to the account. Below code can be customised using custom logic for different scenarios like in the Trigger to automatic encrypt based on the condition etc.

APEX:

// below method takes account id as parameter for which we will be inserting the attachment
Public static void encrypt(String accId, String fileName, Blob fileContent){ 
 
    //EncryptionKey__c is a custom setting where we would be storing private key, insertion is only
    //one time activity. Please be very careful in managing the KEY it should not get deleted else 
    //the document would not be decrypted.

    EncryptionKey__c ek = EncryptionKey__c.getValues('Private Key');
    if(ek.Key__c == null){
        Blob cryptoKey = Crypto.generateAesKey(256);
        ek.Key__c = EncodingUtil.base64Encode(cryptoKey);
        update(ek);
    }
    system.debug(ek.Key__c);

    Blob cryptoKey = EncodingUtil.base64Decode(ek.Key__c); 

    //calling other method which actually encrypt and upload the file as an attachment
    encryptlargeBlob(fileContent,cryptoKey, accId, fileName); 
}


// I am using Future method here because sometimes file size is big and system throws time out 
// exception, to avoid this we can use future for increased limits

@future
Public Static Void encryptlargeBlob(Blob largeBlob, Blob key, String accId, String fileName)
{
    String blobString=EncodingUtil.base64encode(largeBlob);
    
    // Below will encrypt the string and will return encrypted blob
    Blob encrypted = Crypto.encryptWithManagedIV('AES256', key, tempBlob);

    Attachment att=new Attachment();
    att.name = fileName;
    att.body = encrypted;
    att.parentId = accId;

    insert att;
}

Using above code you can easily Encrypt the document, the decryption part is different, Please find my other post for decryption.

Please be careful while playing with Encryption and do proper testing based on your scenario.