One of my recent project was in banking domain. So I had to implement password policies, for that I used devise gem.
Password policies :
1 - Enforce password history - 5 password should be remembered
2 - maximum password age - 30 days
3 - minimum password length - 10 letters
4 - password must meet complexity requirements - Should be a combination of letters, numbers and symbols
5 - Account lockout threshold -5
6 - Account lockout duration - 30 minutes
7 - Email validation - Accept only emails of allowed set of domains
Most of the requirents mentioned above are achivable with simple cofigurations in Devise initializer. But to implement Password expirable, Password archivable and password complexity requirements check I used security extension devise_security_extension.
In this post I assume that we already had devise setup in our project. Now we need to add devise_security_extension in to our project.
1
gem 'devise_security_extension'
After you installed Devise Security Extension you need to run the generator:
1
rails generate devise_security_extension:install
The generator will inject the available configuration options into the existing Devise initializer.When you are done, you are ready to add Devise Security Extension modules on top of Devise modules to any of your Devise models.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable,
:password_expirable, :password_archivable, :expirable, :lockable
end
1 - Enforce password history
Uncomment configuration password_archiving_count and deny_old_passwords in Devise initializer and also add a migration creating old_passwords tables.
1234567
Devise.setup do |config|
# How often save old passwords in archive
config.password_archiving_count = 5
# Deny old password (true, false, count)
config.deny_old_passwords = true
end
2 - maximum password age - 30 days
Uncomment configuration expire_password_after and change to 1.months and also add a migration to store .
1
# config.expire_password_after = 1.months
12345
create_table :the_resources do |t|
# other devise fields
t.datetime :password_changed_at
end
add_index :the_resources, :password_changed_at
Replace our devise model with the_resources.
12345
create_table :users do |t|
# other devise fields
t.datetime :password_changed_at
end
add_index :users, :password_changed_at
3 - minimum password length - 10 letters
12
# Range for password length.
config.password_length = 10..128
4 - password must meet complexity requirements - Should be a combination of letters, numbers and symbols Add password_regex with Regular expression which satisfies our needs.
12
# Need 1 char of A-Z, a-z and 0-9 and special charactor
config.password_regex = /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W])/
5 - Account lockout threshold -5
123
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
config.maximum_attempts = 5
6 - Account lockout duration - 30 minutes
12
# Time interval to unlock the account if :time is enabled as unlock_strategy.
config.unlock_in = 30.minutes
7 - Email validation - Accept only emails of allowed set of domains
For this, I added a custom validator which will check the domain name of user entered an email.
123456789101112131415161718
validate :presence_of_domain_in_email
def presence_of_domain_in_email
email_domain = email.split("@").last.downcase
allowed_domains = User.allowed_domains
unless allowed_domains[email_domain]
errors.add :email, "This email domain is not valid. "
end
end
def self.allowed_domains
{
'gmail.com' =>'gmail.com',
'example.com' => 'example.com',
'example1.in' =>'example1.in'
}
end
Apipie-rails is a DSL and Rails engine for documenting your RESTful API. Instead of the traditional use of #comments, Apipie lets you describe the code, through the code. With Apipie you can specify the methods available to your API, describe every possible parameter. Apipie using Ruby syntax so no need to learn yet another syntax. The documentation is available from within your app (by default under the /apipie path.)
Getting started
Add Apipie to Gemfile
1
gem 'apipie-rails'
after bundle install, initialise Apipie
1
rails g apipie:install
Now confirgure the basic settings in file config/initializers/apipie.rb
12345678
Apipie.configure do |config|
config.app_name = "DemoApp"
config.api_base_url = "/api/v1"
config.doc_base_url = "/apidoc"
# were is your API defined?
config.api_controllers_matcher = "#{Rails.root}/app/controllers/api/v1/*.rb"
config.app_info = "DemoApp REST API "
end
Now you can start documenting your resources and actions
Resource Description:
You can describe a resource on the controller level. The description is introduced by calling resource_description do … end.
The following are some of keywords available (all are optional):
resource_id - How the resource will be referenced in Apipie (paths, see command etc.); by default controller_name.downcase is used.
name - Human readable name of resource. By default class.name.humanize is used.
short - Short description of the resource (it’s shown on both the list of resources, and resource details)
Example is given below :
123
resource_description do
short "API for managing User Profile"
end
Method Description
This using to describe methods available to your API.
api - Describe how this method is exposed, and provide a short description. The first parameter is HTTP method (one of :GET/:POST/:PUT/:DELETE). The second parameter is the relative URL path which is mapped to this method. The last parameter is the methods short description.
1
api :GET, '/user', "Fetch User Profile"
param - Look at Parameter description section for details.
description -Full method description, which will be converted into HTML by the chosen markup language processor.
1234
description <<-EOS
== Books
This API is used to fetch all the books.
EOS
example - Provide an example of the server response; whole communication or response type. It will be formatted as code.
To see more options refer here
Example of a user controller with api documentation is given below
class Api::V1::UsersController < Api::ApiController
resource_description do
short "API for managing User Profile"
end
api :GET, '/user', "Fetch User Profile"
description <<-EOS
== Fetch User Profile
This API is used to fetch the user profile details.
=== Authentication required
Authentication token has to be passed as part of the request. It can be passed as parameter(auth_token) or HTTP header(AUTH-TOKEN).
EOS
formats ['json']
error :code => 404, :desc => "User Profile not yet created"
def show
if @user.nil?
render :status => :not_found, :json => {:message => "User Profile not yet created"}
else
render :status => :ok, :json => {:user=>@user}
end
end
api :PUT, '/user', "Update User Profile"
description <<-EOS
== Update User Profile
This API is used to update the user profile details.
=== Authentication required
Authentication token has to be passed as part of the request. It can be passed as parameter(auth_token) or HTTP header(AUTH-TOKEN).
EOS
error :code => 406, :desc => "User Profile not yet created"
formats ['json']
param :user, Hash, :description => "User" do
param :name, String, :desc => "Name", :required => true
param :email, String, :desc => "Email", :required => false
param :gender, String, :desc => "Gender (1: Male, 2: Female)", :required => true
param :photo, ActionDispatch::Http::UploadedFile, :desc => "User Image", :required => false
param :address, String, :desc => "Address", :required => false
end
def user_profile
if @user.nil?
render :status => :not_acceptable, :json => {:message => "User not exists"}
else
@user.update_attributes(users_params)
@user.save!(:validate=>false)
render :status => :ok, :json => {:user =>@user,:message => "User updated"}
end
end
private
def users_params
params.require(:user).permit(:name, :email, :gender, :photo,:address)
end
end
we can add example data in doc/apipie_examples.yml
Spree is a fully-featured e-commerce solution that can be easily integrated into a Rails application. If you need to turn a Rails app into a store that sells products then Spree is one of the quickest ways to do this. We can customise all the built-in features in Spree and can also and new features and fields to Spree models.
In this post, I am discussing adding an extra field for the uploading company logo into products. For customising view of product form we can use Deface. To add has_attached_file relation to product model we use decorator.
First we need to create migration for adding company logo field to spree_products table.
12345
class AddCompanyLogoToSpreeProducts < ActiveRecord::Migration
def change
add_attachment :spree_products, :company_logo
end
end
To add has_attached_file relation to product model, add product decorator to file app/model/spree/product_decorator.rb
Now we only can add file upload filed to product form using deface.
Deface is a standalone Rails library that enables you to customize Erb templates without needing to directly edit the underlying view file. Deface allows you to use standard CSS3 style selectors to target any element (including Ruby blocks), and perform an action against all the matching elements
Add deface code into app/overrides/company_logo_to_admin_product.rb
Refinery CMS is an Rails-based CMS that supports Rails 3.2 and 4.1. We can make Refinary CMS Multilingual with i18n Translations.
For this add the gem to Gemfile
ruby
1
gem 'refinerycms-i18n'
Run the generator
ruby
1
rails g refinery:i18n
Change the language settings
In Refinery’s settings find I18n Translation Frontend Locales (Refinery) and add the ISO country name.
config/initializers/refinery/i18n.rb
HTML5 allows us to implement client-side form validation without any JavaScript coding. However, error messages are hard-coded to the browser. In my recent project I faced situation, I have to use custome error message and show error message in both english and arabic. I achived error message customisation with Civem.js which let you easily change the message to whatever you wish.
Following are steps to add custom error messages to our project.
1 - Grab the latest download
2 - Add the civem.js script to your page
3 - Start using the custom error message attributes on your input, textarea and select elements
4 - To customise required field error message use data-errormessage-value-missing attribute
6 - For showing pattern missmatch, set custome error message on attribute data-errormessage-pattern-mismatch
there are some other attributes also, that we can use to set specific error messages
OpenShift is a Platform as a Service (PaaS) from RedHat. It’s great for deploying web applications as you can setup/scale/manage apps quickly without any hassle, just like Heroku. It is open source and written in Ruby.
To get started create a free Account. You get 3 small gears (resource container/unit : one small gear is equivalent to 512 MB RAM and 1GB storage) for free. Once you are signed up, install the OpenShift RHC Client Tools by running these commands in a terminal
12
gem install rhc
rhc setup
We can deploy rails application by adding OpenShift as a remote repo.
1- Create a new application in oppenshift account, then get the git URL for your new application. This was shown to you when you created your application,through the web console
2- Add your OpenShift repo as a remote repo
1
git remote add openshift <OpenShift repo URL>
3- Configure Database
Since your database address may change, you will need to access it using an environment variable. A random username and password were also generated for you when your application was created. But you don’t need to hardcode it into your application, there are environment variables for that too!
Add this configuration to database.yml file
4- Now that your app is configured properly, it’s time to deploy it to OpenShift. To do that, simply run a git push
1
git push openshift master
If everything went well, your app should deploy and be accessible. If not, pay attention to the output from the git push, if anything failed, it will tell you there.
If your application requires some persistent directory for your data then you can use directory (app-root/data/) you can access this directory in your application using environment variable OPENSHIFT_DATA_DIR
5- Managing apps:
To ssh into your server, type:
If you want to associate your own domain name eg. (www.yourdomain.com) with your Openshift rails application URL then you will need to create URL alias as shown below
1
rhc alias add railsapp www.yourdomain.com
then change cname records in your DNS provider account.
Best in place is a j Query based Ajax plug in that can help us to add in place editing to our application that takes profit of Restful server-side controllers to allow users to edit stuff with no need of forms. Usage of this gem in rails application is well documented in github page. You can checkout their live demo here. In this post I concentrating on how we can use best in place gem with is active admin pages.
To add Best in Place to our app we first need to add its gem to our application’s Gemfile and run bundle.
For my current project I had to add nested form for belongs_to relationship. After lots of searching i found a solution.
12345
class Product<ActiveRecord::Base
belongs_to :cost, :class_name => 'Currency', foreign_key: 'cost_id'
accepts_nested_attributes_for :cost
attr_accessor :cost_id
end
12345
class Currency < ActiveRecord::Base
def self.currency_types
['SAR','AED','USD','EUR','INR']
end
end
123456789101112131415161718192021222324
ActiveAdmin.registerProductdo
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs "Details" do
f.input :name
f.inputs "cost" do
f.semantic_fields_for :cost_attributes do |j|
j.inputs do
j.input :currency_type, :as => :select, :collection => Currency.currency_types,:label =>'Cost'
j.input :value
end
end
end
end
end
f.actions
end
controller do
def permitted_params
params.permit product: [:name,cost_attributes:[:id,:currency_type,:value]]
end
end
end
FullCalendar is a jQuery plugin that provides a full-sized drag drop calendar like the one below. It uses AJAX to fetch events on-the-fly for each month and is easily configured to use your own feed format (an extension is provided for Google Calendar. It is visually customizable and exposes hooks for user-triggered events (like clicking or dragging an event). It is open source licensed under an MIT license
Step 1 : Download the JQuery fullcalendar plugin by here and add fullcalender.js and fullcalender.css into javascripts and stylesheets folder.Fullcalendar is also available as a gem for Ruby on Rails which fits well with Asset Pipeline.
1
gem 'fullcalendar-rails'
Once the gem is installed, include fullcalendar javascript and css assets to your js and css file
Step 2 : In view page index.html.erb or some other html.erb page add a div with id ‘calendar’
Then add following code to js file