Learn the powerful enterprise adaptable database:

Getting Started With ADABAS & Natural

Tuesday, April 25, 2017

Apps Script Url Shortener


.
Apps Script Url Shortener
This script actually uses goo.gl url shortening service.
However, having an apps script to carry out the shortening service gives an advantage of a custom API that can be called by other web or mobile apps.

Edit Script

Util.gs
function shortenUrls(urls){
 /*urls items are separated by a space*/
 output=[]
  var pattern = new RegExp(/(http|ftp|https):\/\/(?!goo.gl)([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/g);
 var matches = urls.match(pattern);
 if (matches != null) {
   for ( var x = 0 ; x < matches.length ; x++) {
     var match = matches[x];
     var url = UrlShortener.Url.insert({
       longUrl: match
     });
     output.push({longurl:match,shorturl:url.id});
   }
 }
 return output
}


function testShortenUrls1(){
 var urls='http://bernama.com http://www.cnn.com';
 Logger.log(shortenUrls(urls))
}
function testShortenUrls2(){
 var urls='http://bernama.com';
 Logger.log(shortenUrls(urls))
}
WebApp.gs
/* web request listeners */
function doGet(e) {
    return handleResponse(e);
}
function doPost(e) {
    return handleResponse(e);
}
/* handle action request */
function handleResponse(e) {
    var lock = LockService.getPublicLock();
    lock.waitLock(30000); // wait 30 seconds before conceding defeat.
    try {
        var cmd = e.parameter.cmd || "";
        if (cmd == "") {
            return TaskMan("default", e);
        } else if (cmd == "shorten") {
          if (e.parameter.passcode=='12345'){
            return TaskMan("shorten", e);
          }else{
             return TaskMan("default", e);
          }
        }
    } catch (e) { /*if error return this*/
        return ContentService.createTextOutput(JSON.stringify({
            "result": "error",
            "error": e
        })).setMimeType(ContentService.MimeType.JSON);
    } finally { /*release lock*/
        lock.releaseLock();
    }
}
TaskMan.gs
/*taskManager*/
function TaskMan(cmd, e) {
  var output = {rescode:0,resdesc:'',reslong:'',resshort:''};  
    switch (cmd) {
      case "default":
        var output = {rescode:0,resdesc:'none'};  
        break;
      case "shorten":
        var strLongUrl = e.parameter.longurl || '';
        if (strLongUrl!=''){
          var result = shortenUrls(strLongUrl)[0];
          output.reslong = result.longurl;
          output.resshort=result.shorturl;
          output.rescode=100;
          output.resdesc='shorten successful';
        }
        break;
    } /*switch*/
    var output = ContentService.createTextOutput(JSON.stringify({
        "result": "success",
        "content": output
    })).setMimeType(ContentService.MimeType.JSON);
    return output;  

}
When you deploy the code as Web Apps, you will get an error message saying your project id needs to be enabled on Google Developer Console.
Go to Google Developer Console.
Browse for the project id.
Click the ENABLE button.

Test

REFERENCE:


.

101 Apps Script Sign Up API


.
101 Apps Script Sign Up API
This project develops a login and sign up apps that stores login details in the Cloud.
We will use Google Apps Script as the back end for this project.

1. Create Apps Script project

1. AppData.gs (Data Setup codes)

(you need to add objDB library)
/* uses library:
   objDB script id: 1o_O_ZkZm1GuTF5J1LYkfntUpiaT0sxDHyhZXL4fQma89mNIB65epbL6H
*/
/* 1-SETUP APP DATA
   Create spreadsheet file (app-data)
   in the same folder as app script file
*/
function setupAppData(){
  var SCPID = ScriptApp.getScriptId();  
  var file = DriveApp.getFileById(SCPID);
  var folders = file.getParents();
  while (folders.hasNext()){
    FOLID=folders.next().getId();
  }  
  FOLDER = DriveApp.getFolderById(FOLID);
  var d = new Date();  
  var t = d.getTime();
  var NEWSST = SpreadsheetApp.create("105-app-data-"+t);
  var TEMP = DriveApp.getFileById(NEWSST.getId());
  FOLDER.addFile(TEMP);
  DriveApp.getRootFolder().removeFile(TEMP);  
  var scriptProperties = PropertiesService.getScriptProperties();  
  scriptProperties.setProperties({
    scpid:SCPID,
    folid:FOLID,
    sstid:NEWSST.getId()
  });
  /*record headers*/
  /*n=name, g=gmail,hpw=hashedpassword, pc=pincode*/
  var arrRecordTitles=["admins","users"];
  var arrRecordHeaders=[
  ["tid","timestamp","an","ae","salt","ahpw","apc","log"],
  ["tid","timestamp","un","ue","salt","uhpw","upc","log"]
    ];
  for (i in arrRecordTitles){
    var Sheet = NEWSST.getSheetByName(arrRecordTitles[i]);
    if (Sheet != null) {
      NEWSST.setActiveSheet(NEWSST.getSheetByName(arrRecordTitles[i]));
      NEWSST.deleteActiveSheet();
    }
    NewSheet = NEWSST.insertSheet();
    NewSheet.setName(arrRecordTitles[i]);
    NewSheet.appendRow(arrRecordHeaders[i]);
    NewSheet.getRange("A2:A").setNumberFormat('@STRING@');    
  }
}
/* 2-INIT APP DATA
   Get the ScriptProperties values
   If empty, call setupApp()
*/
function initAppData(){
  var SCRIPTPROP = PropertiesService.getScriptProperties();  
  var objProp=SCRIPTPROP.getProperties();
  //if objProp is empty then call setupApp()
  if (Object.keys(objProp).length == 0){
    setupAppData();
    SCRIPTPROP = PropertiesService.getScriptProperties();    
  }
  //Logger.log(SCRIPTPROP.getProperties());  
  /* projectkey=MJMF2lqsgWV-I-dlyqJN6OrljYCrJdQKl */
  var DB1 = objDB.open(SCRIPTPROP.getProperty("sstid"));  
  return DB1;
}
/* 3-REMOVE APP DATA
   Get SSTID (if any)
   Send file to trash
*/
function delAppData(){
  var SCRIPTPROP = PropertiesService.getScriptProperties();  
  var objProp=SCRIPTPROP.getProperties();
  if (Object.keys(objProp).length != 0){
    SSTID=SCRIPTPROP.getProperty("sstid")||'';
    if (SSTID!=''){
      DriveApp.getFileById(SSTID).setTrashed(true);
      SCRIPTPROP.deleteAllProperties();
      }
  }
}

2. Crypto.gs (Hash function)

eval(UrlFetchApp.fetch('https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js').getContentText());
function testCryptoJS() {
  var hash = CryptoJS.SHA256("Message");
  /*alert(hash.toString(CryptoJS.enc.Base64));*/
  Logger.log(hash.toString(CryptoJS.enc.Base64));  
}

3. Jsrsasign (JWT function)

var navigator = {};  
var window = {};  
eval(UrlFetchApp.fetch('https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js').getContentText());
/*refer http://programming-steps.blogspot.my/2017/04/apps-script-and-json-web-token.html */
function tknMakeToken(objPayload,tpw){
  var strToken=KJUR.jws.JWS.sign(null, '{"alg":"HS256"}', objPayload, {"utf8": tpw});
  return strToken;
}
function tknVerifyToken(strToken,tpw){
  return KJUR.jws.JWS.verifyJWT(strToken, {"utf8": tpw}, {alg: ["HS256"]});
}
function tknGetPayload(strToken){
  var objPayload= KJUR.jws.JWS.readSafeJSONString(b64utoutf8(strToken.split(".")[1]));
  return objPayload;
}
function testTkn(){
  var tpw='password';
  strToken=tknMakeToken({un:'aba',ug:'aba@gmail.com'},tpw);
  Logger.log(strToken);
  isValid=tknVerifyToken(strToken,tpw);
  Logger.log(isValid);
  objPayload=tknGetPayload(strToken);
  Logger.log(JSON.stringify(objPayload));
  /*output
    eyJhbGciOiJIUzI1NiJ9.eyJ1biI6ImFiYSIsInVnIjoiYWJhQGdtYWlsLmNvbSJ9.3uybMvG8tBcdq3hwFoNVYHDJPPiKbnT1fIwda90nRak
    true
    {"un":"aba","ug":"aba@gmail.com"}  
    */
}

4. UserTasks (user task functions)

/*taskManager*/
function userTasks(cmd, e) {
  var DB1=initAppData(); //call initAppData() in AppData.gs to return objDB
  var tpw="p4$$w0rd";
  var output = {resdata:0,resdesc:'',resdata:''};  
  switch (cmd) {  
    case "reguser":/*rescode:100*/
      var ue = e.parameter["ue"] || "";
      var pw = e.parameter["pw"] || "";      
      if(ue!="" && pw!=""){
        objExistingRecord=objDB.getRows(DB1,'users',[],{ue:ue})[0] ||{};
          if (Object.keys(objExistingRecord).length >0 ){
            output.rescode=2;
            output.resdesc='email already exists';          
          }else{
            /*prepare template*/
            var objRecord={tid:0,timestamp:0,un:"-",ue:"-",salt:0,uhpw:0,upc:0,log:0};
            /*get values from parameter (if exists)*/
            for(var key in objRecord) {
              if (e.parameter[key]) {
                Logger.log(key);
                objRecord[key]=e.parameter[key]
              };
            }
            /*set uhpw*/
            var pw=e.parameter['pw'] || "";
            if (pw!=""){
              var uhpw = CryptoJS.SHA256(pw);
              objRecord['uhpw']=uhpw.toString(CryptoJS.enc.Base64);
            }
            /*set timestamp*/
            var d = new Date();
            objRecord.timestamp = d;
            /*set tid*/
            if (objRecord.tid==0){
              objRecord.tid = String(d.getTime());
            }
            /*insert new record*/
            var newrecord=objDB.insertRow( DB1, 'users',objRecord );
            Logger.log(newrecord);
            if (newrecord==1){
              output.rescode=0;
              output.rescdec='reg successful';
              output.resdata=objDB.getRows(DB1,'users',['ue'],{tid:objRecord.tid})[0];
              }
          }
        }else{
          output.rescode=1;
          output.resdesc='required input missing'; /*ue pw missing*/
        }
       
      output.rescode=100+output.rescode;
      Logger.log(output);
      break;
    case "loguser":/*rescode:200*/
      var ue = e.parameter["ue"] || "";
      var pw = e.parameter["pw"] || "";              
      if(ue!="" && pw!=""){  
        objExistingRecord=objDB.getRows(DB1,'users',['ue','uhpw'],{ue:ue})[0] ||{};
        Logger.log(objExistingRecord);
          if (Object.keys(objExistingRecord).length >0 ){
            var uhpw=objExistingRecord.uhpw;
            var hpw = CryptoJS.SHA256(pw);
            Logger.log(hpw.toString(CryptoJS.enc.Base64));
            if (hpw.toString(CryptoJS.enc.Base64)==uhpw){
                     output.rescode=0;
                     output.resdesc='log successful';    
                     output.resdata=tknMakeToken({ue:ue},tpw);
            }else{
              output.rescode=3;
              output.resdesc='incorrect login'; /*incorrect password*/                          
            }
          }else{
            output.rescode=2;
            output.resdesc='user not found'; /*user not found*/              
          }
      }else{
        output.rescode=1;
        output.resdesc='required input missing'; /*ue pw missing*/    
     
      }
   
      output.rescode=200+output.rescode;
      Logger.log(output);
      break;

    case "setuser":/*rescode:300*/
      /*check token*/
        var ut = e.parameter["ut"] || "";    
        if(ut!=""){ /*token param value*/
          if(tknVerifyToken(ut,tpw)==true){ /*token param verified*/
            objPayload=  objPayload=tknGetPayload(ut);
            Logger.log(JSON.stringify(objPayload));
            var ue = e.parameter["ue"] || "";    
            Logger.log(ue);
            if(ue!=""){ /*ue param value*/
               if(ue==objPayload.ue){/*ue token matched*/
                 var objUser=objDB.getRows(DB1,'users',['ue','ue'],{ue:ue})[0] ||{} ;
                   if (Object.keys(objUser).length >0 ){ /*user exists*/
                     output.rescode=0;
                     output.resdesc='set successful';    
                     output.resdata=objUser;                    
                   } /*user exists*/
                   else { /*user not exists*/
                     output.rescode=5;
                     output.resdesc='user not exists';                  
                   }  /*user not exists*/
                }  /*ue token matched*/
                else{  /*ue token not matched*/
                output.rescode=4;
                output.resdesc='ue token not matched';                
                } /*ue token not matched*/
              }/*ue param value*/
              else{/*ue param value missing*/
                output.rescode=3;
                output.resdesc='ue param value missing';
              }/*ue param value missing*/
        } /*token param verified*/
        else{  /*token param not verified*/
          output.rescode=2;        
          output.resdesc='token not verified';
        } /*token param not verified*/
           }/*token param value*/
           else{/*token param value missing*/
             output.rescode=1; /*ut not valid*/
             output.resdesc='missing token value';
           }/*token param value missing*/
       
     
      output.rescode=400+output.rescode;
      Logger.log(output);
      break;



  } /*switch*/

  return ContentService.createTextOutput(JSON.stringify({
    "result": "success",
    "data": output
    })).setMimeType(ContentService.MimeType.JSON);
} /*taskManager*/
function testRegUser(){
  var e = {parameter: {cmd: "reguser",
    un:'aba',
    pw:'@64',    
    ue:'aba@gmail.com'
    }};
    Logger.log(userTasks("reguser",e));
}
function testRegUserWithoutUe(){
  var e = {parameter: {cmd: "reguser",
    un:'aba'
    }};
    Logger.log(userTasks("reguser",e));
}
function testRegUserWithoutUePw(){
  var e = {parameter: {cmd: "reguser",
    un:'aba'
    }};
    Logger.log(userTasks("reguser",e));
}
function testLogUser(){
  var e = {parameter: {cmd: "loguser",
    ue:'aba@gmail.com',
    pw:'@64',  
    }};
    Logger.log(userTasks("loguser",e));
}
function testLogUserWithoutUePw(){
  var e = {parameter: {cmd: "loguser",
    }};
    Logger.log(userTasks("loguser",e));
}
function testLogUserNotFound(){
  var e = {parameter: {cmd: "loguser",
    ue:'abu@gmail.com',
    pw:'@6V',  
    }};
    Logger.log(userTasks("loguser",e));
}
function testLogUserIncorrectLogin(){
  var e = {parameter: {cmd: "loguser",
    ue:'aba@gmail.com',
    pw:'a6a',  
    }};
    Logger.log(userTasks("loguser",e));
}
function testSetUser(){
  var e = {parameter: {cmd: "setuser",
    un:'abaa',
    ue:'aba@gmail.com',
    ut:'eyJhbGciOiJIUzI1NiJ9.eyJ1ZyI6ImFiYUBnbWFpbC5jb20ifQ.pHg2mkqce_8jt3roCWgxO5dZ3gQlNnrKQw4uChcymUs',  
    }};
    Logger.log(userTasks("setuser",e));
}
function testSetUserNoTkn(){
  var e = {parameter: {cmd: "setuser",
    }};
    Logger.log(userTasks("setuser",e));
}
function testSetUserInvalidTkn(){
  var e = {parameter: {cmd: "setuser",
    ue:'aba@gmail.com',
    ut:'eyJhbGciOiJIUzI1NiJ9.eyJ1ZyI6ImFiYUBnbWFpbC5jb20ifQ.pHg2mkqce_8',  
    }};
    Logger.log(userTasks("setuser",e));
}
function testSetUserUeMismatch(){
  var e = {parameter: {cmd: "setuser",
    un:'aba',
    ue:'aba@gmail.com',
    ut:'eyJhbGciOiJIUzI1NiJ9.eyJ1ZyI6ImFidUBnbWFpbC5jb20ifQ.UL3oWSyEB7beYhQUdcQ8I1ih4bIjGBRfus0Ty64jSh8',  
    }};
    Logger.log(userTasks("setuser",e));
}
function testSetUserUeNotFound(){
  var e = {parameter: {cmd: "setuser",
    un:'abuu',
    ue:'abu@gmail.com',
    ut:'eyJhbGciOiJIUzI1NiJ9.eyJ1ZyI6ImFidUBnbWFpbC5jb20ifQ.UL3oWSyEB7beYhQUdcQ8I1ih4bIjGBRfus0Ty64jSh8',  
    }};
    Logger.log(userTasks("setuser",e));
}

5. WebApps.gs (Web API functions)

function doGet(e) {
  return handleResponse(e);
}
function doPost(e) {
  return handleResponse(e);
}
/* handle action request */
function handleResponse(e) {
  var lock = LockService.getPublicLock();
  lock.waitLock(30000); // wait 30 seconds before conceding defeat.
  try {
    var cmd = e.parameter.cmd;
   
    if (cmd == "reguser") {
      return userTasks("reguser", e);
    } else if (cmd == "loguser") {
      return userTasks("loguser", e);
    } else if (cmd == "setuser") {
      return userTasks("setuser", e);
    }else{
       return ContentService.createTextOutput(JSON.stringify({
         "result": "success",
         "data": "hello!"
         })).setMimeType(ContentService.MimeType.JSON);    
    }
   
  } catch (e) { /*if error return this*/
    return ContentService.createTextOutput(JSON.stringify({
      "result": "error",
      "error": e
    })).setMimeType(ContentService.MimeType.JSON);
  } finally { /*release lock*/
    lock.releaseLock();
  }
}

2. Test

Use www.resttesttest.com or Chrome Postman App.
The above parameter gets the following response.

{"result":"success","data":{"resdata":"eyJhbGciOiJIUzI1NiJ9.eyJ1ZSI6ImFiaWlAZ21haWwuY29tIn0.sTxLFZ3zEiVV_d4HgHhS8DdlsMczgu8_WXgj-o8oNXY","resdesc":"log successful","rescode":200}}

.