COOKIES! This blog uses cookies!
I am completely out of control of cookies here, otherwise I would have disabled them (it is controlled by the platform).
If you don't like cookies and being tracked please leave this blog immediately.

Monday, 23 February 2015

Eclipse hotkeys / shortcuts

These are useful shortcuts I always forget after a few weeks not using Eclipse:

Show shortcuts list: ctrl+shift+L

Spellcheck suggestions: ctrl+1
Quick fix suggestions: F2

Rename all occurencies: shift+alt+R
Open resource: ctrl+shift+R
Show Occurrences: ctrl+shift+U
Enable “Block”(rectangle) selection: alt+shift+A
Duplicate Line: ctrl+alt+UP

Select blocks of code: alt+shift+Up (each press selects block one level higher)
De-select blocks of code: alt+shift+Down (each press selects block one level higher)

type hinting (for dynamic typing languages): /* @var $varName \Type */


Preserve case replace:
ctrl+f (edit->find/replace)
tick "Regular expressions" check-box
Find: general
Replace with: \CSeparate

Here \C is a regex retain-case operator it will cause the following results of replacements:
general->separate
General->Separate

Friday, 20 February 2015

Get document PDF preview in Alfresco

Alfresco is able to transform document types.
For example transform MSWord doc file into PDF

The quick way to access PDF preview (or of any other available type) is a ThumbnailService

An example:
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
//...
public class YourClass{
  //...
  @Autowired
  ThumbnailService thumbnailService;
  //...
  public yourMethod {
      NodeRef documentNodeRef = new NodeRef(
          request.getParameter("nR")
      );
      NodeRef pdfPreviewNodeRef = null;
      //...
      pdfPreviewNodeRef = thumbnailService.getThumbnailByName(
          documentNodeRef, ContentModel.PROP_CONTENT, "pdf"
      );
      if (pdfPreviewNodeRef==null) {
        //generate a new PDF preview if one is not available yet
        pdfPreviewNodeRef = thumbnailService.createThumbnail(
            documentNodeRef, ContentModel.PROP_CONTENT,
            "application/pdf", new SWFTransformationOptions(), "pdf"
        );
      }
      //...
  }
  //...
}

Wednesday, 21 January 2015

A good manual on software versioning

Semantic Versioning: http://semver.org/

Briefly:

Given a version number MAJOR.MINOR.PATCH, increment the:
  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Wednesday, 14 January 2015

Alfresco Javascript webscript Debuggers

Just found that there are actually two of them:

One for the Alfresco repository debugging:
/alfresco/service/api/javascript/debugger
(may be http://127.0.0.1:8080/alfresco/service/api/javascript/debugger)

And one for the Alfresco share debugging:
/share/page/api/javascript/debugger
(may be http://127.0.0.1:8081/share/page/api/javascript/debugger)

Webscript indexes accordingly are:
/alfresco/service/index
(http://127.0.0.1:8080/alfresco/service/index)

and

/share/service/index
(http://127.0.0.1:8081/share/service/index)


Debuggers sometimes won't catch webscripts evaluated: you may need to clean up the project and do "clear dependency caches" and "refresh web scripts" on webscript indexes service pages.

Tuesday, 4 November 2014

JWT usage example

Good, easy to understand JSON web token (JWT) usage example, which does not contain much unrelated stuff:
https://github.com/auth0/angular-token-auth

Article with explanation:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

Listings just in case if it suddenly disappear:

auth.server.js
var express = require('express');
var bodyParser = require('body-parser');

var jwt = require('jsonwebtoken');  //https://npmjs.org/package/node-jsonwebtoken
var expressJwt = require('express-jwt'); //https://npmjs.org/package/express-jwt


var secret = 'this is the secret secret secret 12356';

var app = express();

// We are going to protect /api routes with JWT
app.use('/api', expressJwt({secret: secret}));

app.use(bodyParser.json());
app.use('/', express.static(__dirname + '/'));

app.use(function(err, req, res, next){
  if (err.constructor.name === 'UnauthorizedError') {
    res.status(401).send('Unauthorized');
  }
});

app.post('/authenticate', function (req, res) {
  //TODO validate req.body.username and req.body.password
  //if is invalid, return 401
  if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) {
    res.status(401).send('Wrong user or password');
    return;
  }

  var profile = {
    first_name: 'John',
    last_name: 'Doe',
    email: 'john@doe.com',
    id: 123
  };

  // We are sending the profile inside the token
  var token = jwt.sign(profile, secret, { expiresInMinutes: 60*5 });

  res.json({ token: token });
});

app.get('/api/restricted', function (req, res) {
  console.log('user ' + req.user.email + ' is calling /api/restricted');
  res.json({
    name: 'foo'
  });
});

app.listen(8080, function () {
  console.log('listening on http://localhost:8080');
});


auth.client.js
var myApp = angular.module('myApp', []);

//this is used to parse the profile
function url_base64_decode(str) {
  var output = str.replace('-', '+').replace('_', '/');
  switch (output.length % 4) {
    case 0:
      break;
    case 2:
      output += '==';
      break;
    case 3:
      output += '=';
      break;
    default:
      throw 'Illegal base64url string!';
  }
  return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
}

myApp.controller('UserCtrl', function ($scope, $http, $window) {
  $scope.user = {username: 'john.doe', password: 'foobar'};
  $scope.isAuthenticated = false;
  $scope.welcome = '';
  $scope.message = '';

  $scope.submit = function () {
    $http
      .post('/authenticate', $scope.user)
      .success(function (data, status, headers, config) {
        $window.sessionStorage.token = data.token;
        $scope.isAuthenticated = true;
        var encodedProfile = data.token.split('.')[1];
        var profile = JSON.parse(url_base64_decode(encodedProfile));
        $scope.welcome = 'Welcome ' + profile.first_name + ' ' + profile.last_name;
      })
      .error(function (data, status, headers, config) {
        // Erase the token if the user fails to log in
        delete $window.sessionStorage.token;
        $scope.isAuthenticated = false;

        // Handle login errors here
        $scope.error = 'Error: Invalid user or password';
        $scope.welcome = '';
      });
  };

  $scope.logout = function () {
    $scope.welcome = '';
    $scope.message = '';
    $scope.isAuthenticated = false;
    delete $window.sessionStorage.token;
  };

  $scope.callRestricted = function () {
    $http({url: '/api/restricted', method: 'GET'})
    .success(function (data, status, headers, config) {
      $scope.message = $scope.message + ' ' + data.name; // Should log 'foo'
    })
    .error(function (data, status, headers, config) {
      alert(data);
    });
  };

});

myApp.factory('authInterceptor', function ($rootScope, $q, $window) {
  return {
    request: function (config) {
      config.headers = config.headers || {};
      if ($window.sessionStorage.token) {
        config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
      }
      return config;
    },
    responseError: function (rejection) {
      if (rejection.status === 401) {
        // handle the case where the user is not authenticated
      }
      return $q.reject(rejection);
    }
  };
});

myApp.config(function ($httpProvider) {
  $httpProvider.interceptors.push('authInterceptor');
});


index.html
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Angular Authentication</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
    <script src="./auth.client.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="UserCtrl">
      <span ng-show="isAuthenticated">{{welcome}}</span>
      <form ng-show="!isAuthenticated" ng-submit="submit()">
        <input ng-model="user.username" type="text" name="user" placeholder="Username" />
        <input ng-model="user.password" type="password" name="pass" placeholder="Password" />
        <input type="submit" value="Login" />
      </form>
      <div>{{error}}</div>
      <div ng-show="isAuthenticated">
        <a ng-click="callRestricted()" href="">Shh, this is private!</a>
        <br>
        <div>{{message}}</div>
        <a ng-click="logout()" href="">Logout</a>
      </div>
    </div>
  </body>
</html>


package.json
{
  "name": "angular-token-auth",
  "version": "0.1.0",
  "dependencies": {
    "body-parser": "^1.9.0",
    "express": "~4.9.0",
    "express-jwt": "~0.2.1",
    "jsonwebtoken": "~0.4.0"
  },
  "description": "Example of Token-based authentication in [AngularJS](http://angularjs.org) with [Express](http://expressjs.com).",
  "main": "auth.server.js",
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/auth0/angular-token-auth.git"
  },
  "keywords": [
    "angular",
    "auth",
    "jwt",
    "express"
  ],
  "author": "",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/auth0/angular-token-auth/issues"
  },
  "homepage": "https://github.com/auth0/angular-token-auth"
}

Wednesday, 24 September 2014

Combine several Q objects programmatically with OR in Django ORM

Say we have dictionary coming from outside (from JSON, for example, containing some data to be used as OR clauses). It is possible to use __or__ to combine them programmatically.

from django.db import models
from operator import __or__ as OR
from django.db.models import Q

#... some code ...
clauses = [{'property':'name__exact','value':'andrew'},{'property':'name__icontains','value':'z'}, ... ]
or_params = []
for or_param in clauses:
    if 'value' in or_param.keys() and 'property' in or_param.keys():
        or_params.append(Q(**dict([(or_param['property'], or_param['value'])])))

Model.objects.filter(reduce(OR, or_params))

Many thanks to Calvin for right keywords

Wednesday, 10 September 2014

Sencha: Catch all events of Observable

Very useful pattern to catch all events of Observable object in Sencha:
Ext.util.Observable.capture(object, function(){
    console.log(arguments);
});


This object might be Store, View, or whatever using Observable mixin. This may be useful to learn how the object work or to catch events before any other on/addListener listeners.

Arguments may wary but it contains at least two objects:
0: {String} always event name
1: {Object} object itself

This may contain other arguments such as Action, changed Model (for Store), String name of the action caused event, Array of changed fields (for Model and Store)

Store usage:
Ext.util.Observable.capture(store, function(){
    if (arguments[0]=='update') {
        /*eventName,store,record,operation,modifiedFields*/
        // Your fancy code here
        store.suspendEvent('update');
    }
});