“88.100.211″ is the pattern meaning “88.100.211*”
apache’s mod_setenvif must be enabled
“order allow,deny” denies all except “Allow” rules
usual “Allow from ip” rules will not work as the load balancer rewrites the “host” header, all requests are coming from the load balancer’s IP
the load balancer should set the X-Forwarded-For header
Purpose of this blog is to show how to integrate Spring Security framework with REST web services implemented using Apache CXF. To authenticate user within Spring Security framework external authentication mechanism based on token is used. The idea is to authenticate Spring Security application against external application – in our case Alfresco.
Dependencies
In order to get required libraries the following ivy script was used:
It might be necessary to remove older versions of some jars.
List of libraries required in the project that should be put in WEB-INF/lib is presented below:
web.xml
Configuration of WEB-INF/web.xml file is presented below. It contains configuration of the following frameworks:
Spring
Spring Security
Apache CXF
Hibernate
We are going to put all the files related to REST web service in path /service/*, therefore in the configuration file above this path is set as url-pattern for Apache CXF Service filter (CXFServlet). Spring Security filter (springSecurityFilterChain) has the same url-pattern set in order to secure REST web services.
Spring configuration file
As defined in WEB-INF/web.xml file Spring configuration file is in the following location ‘/WEB-INF/classes/applicationContext.xml’ and is presented below. It includes files with configuration of beans required by Spring Security (resources/context/security.xml) and Apache CXF REST web service (resources/context/service.xml). Section with namespace ‘jaxrs’ corresponds to configuration of Apache CXF REST web service and section with namespace ‘security’ corresponds to configuration related to Spring Security. They will be described in more detail in the following sections.
Apache CXF REST web service configuration
As defined in ‘/WEB-INF/classes/applicationContext.xml’ (jaxrs:server) REST service consists of one service – userService. Corresponding Spring bean (jaxrs:serviceBeans) is called ‘userServiceBean’ and is defined in /WEB-INF/classes/resources/context/service.xml file as follows:
In addition the configuration defines extension mappings (jaxrs:extensionMappings), enables logging (cxf:logging), and selects Jackson JSON-processor for processing JSON data (jaxrs:providers). </p>
UserServiceImpl class is presented below. It implements UserService interface, produces JSON content, and path to the service is /user. It also autowires session factory, which is hibernate session factory, and defines one method retrieveProperties(). retrieveProperties() method can be accessed using the following URL: /service/user/retrieveProperties. It responds to GET request and returns JSON (determined by @Produces annotation of UserServiceImpl class) with list of property names. The URL depends on configuration of url-pattern in Apache CXF filter (web.xml) and @Path annotations.
Spring Security related configuration
As mentioned in previous section Spring security configuration is located in ‘/WEB-INF/classes/resources/context/security.xml’. Let’s assume the following scenario of authentication in Spring Security framework. There is external authentication service that we use to authorise user within Spring Security framework. When request to /service/user/retrieveProperties is made it also contains a ticket passed as parameter in URL, i.e., /service/user/retrieveProperties?ticket=.... The ticket contains all the information necessary to authenticate user in external service and see whether the ticket is still valid. External service returns all the information required by Spring Security framework to authenticate the user. The related configuration is presented below and will be discussed in the following part of this section.
myAuthenticationProcessingFilter bean – AuthenticationProcessingFilter class
Responsibility of myAuthenticationProcessingFilter bean is to take ticket from the request and issue request to external authentication service to get user details. The user details are then translated to the roles defined in Spring Security annotations. AuthenticationProcessingFilter class extends AbstractAuthenticationProcessingFilter class which demands implementation of Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) method. This method performs actual authentication – in our example obtains user details from external authentication service in the basis of the ticket.
attemptAuthentication method is invoked only when boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) method returns ‘true’. Implementation of requiresAuthentication in AbstractAuthenticationProcessingFilter class matches filterProcessesUrl (given in constructor of AuthenticationProcessingFilter object) against request URL, because we do not want to define access to REST web service methods on the basis of their URLs, we have to overwrite this behaviour. We assume that if there is no authentication object in context then requiresAuthentication method should return true. When authentication object is obtained getAuthenticationManager().authenticate(authentication) is invoked in the code to authenticate the user using authentication provider (AuthenticationProvider).
successfulAuthentication method is invoked when credentials are retrieved from third party authentication system and attemptAuthentication does not throw AuthenticationException exception. The method saves authentication object in security context and invokes next filter from the chain.
Implementation of myAuthenticationProcessingFilter bean, which checks ticket in Alfresco is presented below. It is assumed that there will be two additional parameters passed to request URL – alf_ticket, workgroup – /service/user/retrieveProperties?alf_ticket=...&workgroup=.... There are the following roles defined in the system:
ROLE_ADMINISTRATOR
ROLE_WORKGROUP_ADMINISTRATOR
ROLE_USER
Depending on the role user should be able to run only allowed web services.
myAuthenticationProvider bean – AuthenticationProvider class
This bean is responsible for returning information whether user is authenticated or not. It implements AuthenticationProvider interface, which defines 2 methods:
Authentication authenticate(Authentication authentication) – This method returns authentication object used by Spring Security for authorization. It checks data provided in authentication object passed as parameter and on that basis decides whether user should be authenticated (authentication.setAuthenticated(true)) or not. In our example if user name (authentication.getPrincipal()) was obtained from external service on the basis of the ticket, it is assumed that user is authenticated. If user is not authenticated BadCredentialsException is thrown.
boolean supports(Class aClass) – This method returns whether AuthenticationProvider object should process the request – authenticate method should be invoked. In that case only authentication object given as a parameter to authenticate method which is of AuthenticationToken type should be processed by authenticate method.
Implementation of myAuthenticationProvider bean is presented below.
Roles definition
Roles are defined in authentication object (AuthenticationToken class). Depending on roles assigned to the user it is possible to allow the user to invoke particular web services and forbid invocation of another.The roles defined in this example are:
The roles are used in the annotations in user service (UserService) interface. The interface is implemented by UserServiceImpl class – userServiceBean bean. In the code below two methods, which are web services, are presented – retrieveOptions and createOption. The first one allows users in all three roles to invoke the web service call, and the second one allows the invocation for only workgroup administrator. The roles are the can invoke particular method are listed in @RolesAllowed annotation.
The corresponding implementation class is presented below:
sync_binlog is a setting that (when set to 0) forces MySQL to flush a write to binary log to disk after every transaction. I have performed a quick test to see how does the setting affect the performance of MySQL and the reliability of the binary log.
Test setup:
Ubuntu Server 13.10 running in VirtualBox
MySQL 5.5.32 from the standard package, default configuration
InnoDB storage engine used
SSD storage but no battery-backed disk
I have tested the performance of a script that inserts 10000 short rows. Each test was repeated 20 times, then machine restarted and series of another 20 tests performed. Higher times for the initial tests (1-4 and 21-24) are most likely related to warm-up after reboot and should really be ignored. After each test, I’ve checked the value of the dirty (not-flushed) caches to validate the result. Note that this is pretty extreme situation – I’m emulating an application that only does writes to the database.
Performance
As expected, with sync_binlog=0 there are plenty of binary log changes to be flushed to disk. There is none when running with sync_binlog=1. On the other hand, the average time to perform 10000 INSERTs jumped from 23 seconds to 41 seconds – nearly doubled.
Reliability
I’ve tested how reliable is each setting by running the script with 10000 INSERTs, forcefully powering off the whole system, starting up again and then comparing records (transactions) written to the database versus those written to binary log. I have tried it few times with both setting and the same results each time:
with sync_binlog=1 the data in the database was always in sync with the binary log. That is, the last record succesfully inserted into the database, matches the last entry in binary log.
with sync_binlog=0, after reboot there were thousands of records persisted in the database but missing from the binary log.
Summary
If you care about binary log (think about master-slave replication for example) set sync_binlog to 1, if you want to squeeze a bit more performance, set it to 0.
This blog describes how to limit upload of files with size exceeding particular value to Alfresco repository.
Implementation
Restriction can be done in ContentServiceImpl class. Let’s extend this class in class CustomContentServiceImpl. We can add sizeLimit variable which is going to keep limit value in bytes and then use this limit in getWriter method.
Now you have to declare new content service bean (contentService). You can do it in alfresco/patch/custom-content-services-context.xml file as follows:
Size limit variable (sizeLimit) can be also defined in alfresco-global.properties and then instead of value, e.g., 2000000 ${sizeLimit} placeholder should be used.
That change should prevent possibility of upload of files, which exceed particular size. In addition, change in Alfresco WebScript (alfresco/templates/webscripts/org/alfresco/repository/upload/upload.post.js) can be made to return appropriate error to Alfresco Share.
This blog introduces sending periodical e-mail reminders in Alfresco Activiti Workflows.
Workflow with periodical e-mail reminders
To send periodical e-mail reminders (as well as to do any other periodical action) we have to start from defining the workflow. Let’s assume that we extend already existing workflow ‘Review And Approve Activiti Process’ defined in file ‘review.bpmn20.xml’. We will add periodical reminder (‘E-mail Reminder’) to review task to remind user that this task is pending by sending him e-mail.
</a>
Corresponding XML looks like follows. Two tasks were added to it:
Timer, which is boundaryEvent with id ‘timer_review’
E-mail Reminder, which is serviceTask with id ‘mailtask_review’
Timer
Complete reference to boundaryEvent can be found here. In our case we care about two attributes:
attachedToRef – indicates task which starts timer
cancelActivity – if set to ‘false’ does not cancel original task (defined in attachedToRef attribute)
Complete reference to timerEventDefinitions can be found here. In our case we selected to use timeCycle element, which specifies repeating interval and can be given as cron expression, e.g., run ‘E-mail Reminder’ task every Monday at 00:00am – 0 0 0 ? * MON
E-mail Reminder
This task is serviceTask, which means that it executes without any user interaction. In our case we define it as ‘org.alfresco.repo.workflow.activiti.script.AlfrescoScriptDelegate’ class to make it possible to write JavaScript code, which uses Alfresco JavaScript API. In this task, simply send e-mail with reminder to user, which was selected as review assignee.
How many lines of code does Moodle have?
The short answer is: core Moodle 2.6 has about 600k lines of code + 3rd party libraries.
Now, the long answer.
A lot of the Moodle code are 3rd party libraries that are copied mostly under “lib” directory and some other places – I have counted those separately. I have also not counted *-min.js and *-debug.js files as duplicates.
After stripping from those, here is the statistic for the core code for the latest Moodle (2.7dev build: 20131122):
The code above works just fine, you can access private properties of different object – as long as you’re the same class. PHP manual confirms the behaviour:
Members declared as private may only be accessed by the class that defines the member.
The purpose of this blog is to show how to enable search for multi-valued properties in advanced search form in Alfresco. Let’s assume that we are looking for authors and we want to find all the documents created by author John or Mary. This feature allows to do this in single query instead of two queries.
Solution
Multi-valued search is already supported in Alfresco, but requires additional configuration. This can be done by adding additional hidden field to advanced search form. The field should follow the name format prop:{name of the filed with values separated by commas}-mode and defines logical operator that should be used to replace commas.
In addition, hidden.ftl form control has to be modified to support providing field value in contextProperty parameter. The changes are presented below:
This blog describes how to create e-mail template in Alfresco and use it for sending e-mail.
Template
E-mail templates are kept in folder Company Home/Data Dictionary/Email Templates, but in general they can be kept in any folder. Let’s assume, that in our template we want to use some variables, which values will be passed during invocation of e-mail action. Our template is saved in Company Home/Data Dictionary/Email Templates/sample_template.ftl and is defined as follows:
Variable ‘firstName’ should be replaced with the name of user the message is send to.
E-mail send action
We will invoke e-mail sending action using Alfresco JavaScript API:
See the screencast below for the description of new moosh feature – code generation. You can download moosh from Moodle plugins, also see the documentation.