RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Build Robust Security into a Rails-Based Wiki System : Page 4

Learn how to add robust security features to a simple wiki system built on the Rails platform.

Changes to the Controller Class
The controller class, WikiController (see Listing 3), changes significantly from the original RailsWiki application. Let's review some of methods with the most notable changes.

The create_account method kicks things off by allowing a user to create his or her own account. If all the parameters passed into this method are valid, the user's account (password file) is created using the WikiUser model class, as demonstrated here:

wu = WikiUser.new user
  wu.create_account pass
  flash[:error] = "Account created; you may login now."

The login method authenticates the user using the WikiUser model class. If the user's credentials are valid, the system establishes a session for the user and forwards him or her to the home view. Otherwise, it sends the user back to the index view with an error message. The following code excerpt demonstrates all of this:

unless wikiuser.valid_password?(pass)
    flash[:error] = "Invalid password."
    redirect_to :action => :index
     session[:user] = wikiuser
     redirect_to :action => :home, :f => DEFAULT_FILENAME

The home method simply gathers a list of wiki pages, encrypted and non-encrypted, which belong to the current user and passes it to the home view, as demonstrated here:

@filelist = []
  list1 = WikiDocument.find_wikis(get_basedir, PLAIN_EXTENSION)
  list2 = WikiDocument.find_wikis(get_basedir, ENCRYPTED_EXTENSION)
  @filelist.concat(list1) unless list1.nil?
  @filelist.concat(list2) unless list2.nil?

The create method creates a blank wiki file with the appropriate extension, as shown here:

if (extname.nil? || (extname != ENCRYPTED_EXTENSION && extname != PLAIN_EXTENSION))
          if (encrypt)
              @filename = @filename + ENCRYPTED_EXTENSION
              @filename = @filename + PLAIN_EXTENSION

The save method calls the internal/private method save_document, which in turn determines the appropriate save method to call on the WikiDocument model class based on whether encryption is required or not, as demonstrated here:

def save_document(filename, content, encrypt)
      if (encrypt)
          WikiDocument.save_encrypted((get_fullpath filename, false), content, (get_session_object).key)
          WikiDocument.save((get_fullpath filename, false), content)

Once a wiki file has been created, these files are read using the private method get_content, which determines whether the file needs to be decrypted or not, as shown here:

@filestat = WikiDocument.attributes(get_fullpath(@filename))
 extname = File.extname(@filename)
  if (extname == ENCRYPTED_EXTENSION)
      @content = WikiDocument.find_encrypted(get_fullpath(@filename), (get_session_object).key)
      @content = WikiDocument.find(get_fullpath(@filename))

One last notable method in the controller class is the authenticate method. This method is called before various methods that require a user to be logged in, that is, they require an active session for the user. This method is automatically called prior to such methods by using Rails' filters as shown in this single line of code:

before_filter :authenticate, :only => [:home, :edit, :view, :print]

Configuration File
The other file worth inspecting is the config/environment.rb file, since it contains various default settings for RailsWiki, as shown here:

WIKI_DIR = "/users"
PASSWORD_KEY = "WikiUserKey"
PASSWORD_FILE = ".railswiki_pass"

The Wrap Up
Part 1 of this article series showed how to build RailsWiki, a very bare bones but functional wiki system. This article added security features to it, namely authentication and encryption. However, many robust wiki systems today tend to contain a lot more features to enable collaboration. Here are some ideas for extending the RailsWiki system even further:

  • Add role-based security (that is, authorization)
  • Add email alerts for notifying others when changes to a file occur
  • Add revisions and ability to roll back to a previous version of a wiki document
  • Add search capabilities using something like the Ferret library

If you decide to add any of the above features, be sure to submit your changes to the RailsWiki open source project on RubyForge and/or notify me, as I would love to use some of them myself!

Anil Hemrajani has developed code for 20 years, published dozens of articles and a popular book, won multiple industry awards, given talks in four continents, built a popular award-winning developer community, and run a successful company. He is currently an independent consultant.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date