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
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:
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))
@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)
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]
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"
PLAIN_EXTENSION = ".wiki"
ENCRYPTED_EXTENSION = ".swiki"
DEFAULT_FILENAME = "untitled" + PLAIN_EXTENSION
PASSWORD_KEY = "WikiUserKey"
PASSWORD_FILE = ".railswiki_pass"
PATH_SEPARATOR = "/"
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!