Secure model mass assignment for administration panels

For the most applications I’m developing I want the users to be able to edit their user data or profile using model mass assignment in Rails.  Moreover I want additionally an easy administration panel for super users who can access all the attributes of the users (and nested attributes) via mass assignment.

Now what’s an easy and rails-like way to allow users and super users to edit exclusively the attributes they have access for? I’ve searched the web and found dirty solutions like accessing the current_user from your model or modifying before_*-handlers. So here is my way.

In the user-model I declare the attributes the user has access to, using attr_accessible:

class User < ActiveRecord::Base
  attr_accessible :login, :email, :birthday, :country, :city, :age_is_public
end

For the administration panel I create a new model which extends the User model. This AdminUser model extends the accessible attributes of the User model for the super user.

class AdminUser < User
  attr_accessible :role, :comment, :level
end

Now I access the User model from the controller for standard users and the AdminUser model from the admin controller.  The verification for a valid and logged in super user is done there.

class UsersController < ApplicationController
  before_filter :login_required
  [..]
  def update
    @user = User.find(current_user.id)
    @user.update_attributes(params[:user])
  [..]
end
class AdminUsersController < ApplicationController
  before_filter :login_required, :admin_required
  [..]

  def update
    @user = AdminUser.find(params[:id])
    @user.update_attributes(params[:user])
  [..]
end

That's it. Nice and clean model mass assignment depending on the security level of the user. This also works nice with nested attributes. Don't forget to add _attributes to your symbol name in attr_accessible in this case (like  :profile_attributes for a has_one relationship with the profile model).

Keywords: admin panel, control panel, rails, nested_attributes_for, mass assignment, attr_accessible, attr_protected

“undefined method `use_transactional_fixtures=’” after upgrading to Rails 2.3.2

After upgrading to Rails 2.3.2 I’ve tried to run the testcases. The following error occured:

test/test_helper.rb:22: undefined method `use_transactional_fixtures=’ for Test::Unit::TestCase:Class (NoMethodError)

Solution:

Test::Unit::TestCase changed to ActiveSupport::TestCase, so simply edit your test/test_helper and change the name of the class.

Keywords: functional test problems

Display problems w/ ATI Xpress 1250 under Jaunty (Ubuntu 9.04)

The flickering bug described in the following was fixed. If you don’t want to wait until it has been released officially, get the deb packages at launchpad:

https://launchpad.net/~tormodvolden/+archive/ppa

After installing you should be able to use the driver with the default EXA acceleration method again. If you’ve changed anything at the xorg.conf to avoid the flickering, don’t forget to reset your xorg.conf after installing the fixed driver.

For the sake of completeness, here is the old workaround:

When I had installed the new Ubuntu release on my notebook (HP Compaq 6715b), I was so happy about the fact, that most problems which had occured with the notebook drivers finally disappeared in Jaunty. But that feeling didn’t last long.

Broadcom WLAN-Chip with WPA2 worked – YAY!, Standby and Hibernation worked – YAY!

But, what’s that? Flickering black and red stripes around the middle of the screen, flashing white stripes and more flickering when scrolling the terminal. OpenGL apps also flicker and display the windows behind the OpenGL window for a split second now and then.

Unfortunately ATI moved the drivers for the graphic chipset ATI Xpress 1250 to their “Legacy” program.  They discontinued their proprietary driver support several months ago. BOOOO!! Tragically Jaunty comes with the new Xorg 7.4, which is NOT supported by this legacy driver.  NO!

Sadly x1250 users have to use the free radeon driver coming with ubuntu.

Ok, let’s set it up to remove the flickering and display problems!

  1. Turn off Compiz completely (System -> Settings -> Appearance -> Visual Effects). This will remove the first problems.
  2. Change the “Accelleration Method” from EXA to XAA.  Edit your /etc/X11/xorg.conf and add the following line to your Device section:
    Option “AccelMethod” “XAA”
    This will remove the rest of the display problems.
  3. Restart Gnome in a clean way. First logout in Gnome, then Switch with Ctrl+Alt+F1 to a shell and do a sudo /etc/init.d/gdm restart
  4. Problems should be gone now

I couldn’t figure out any difference in perfomance after switching the AccelMethod to XAA. But neither EXA nor XAA can’t control the x1250 chipset as the proprietary driver of ATI did. It’s pretty slow and it seems that the free driver handles the chipset not correctly, because the system temperature is higher now and the notebook fan is nearly always activated.

I hope now, that there will be a better free driver of this chipset soon. And I also hope, that I could help you a little bit in how to get rid of the display problems with the free graphic driver radeon and the x1250 chipset.

Any new ideas or news are welcome!

Keywords: flickering, red black, display problems, X1250, Xpress1250, ATI, white stripes, compiz, desktop effects

Switching between OS and CEGUI cursor (windowed mode)

I’m using the following snippet in my mouseMoved-Event to handle the switching between the windows os mouse cursor and the cegui mouse cursor when entering/leaving the RenderWindow.

      if (mMouseInWindow)
      {
        CEGUI::System::getSingleton().injectMousePosition( arg.state.X.abs, arg.state.Y.abs );
        if (arg.state.X.abs == 0 || arg.state.Y.abs == 0 ||
            arg.state.X.abs == mWindowMaxWidth || arg.state.Y.abs == mWindowMaxHeight)
        {
          CEGUI::MouseCursor::getSingleton().hide();
          ShowCursor(true); // windows only
          mMouseInWindow = false;
        }
      }
      else if (arg.state.X.abs > 0 && arg.state.Y.abs > 0 &&
        arg.state.X.abs < mWindowMaxWidth && arg.state.Y.abs < mWindowMaxHeight)
      {
        CEGUI::MouseCursor::getSingleton().show();
        ShowCursor(false); // windows only
        mMouseInWindow = true;
      }

Smilies in Rails using BBCodeizer

I’ve already described how to enable support for Smilies in Rails using RedCloth. If you want to use BBCodeizer instead of RedCloth (Textile), here’s how to do it. We need to extend the BBCodeizer class. We could do this by creating a file in our /lib directory (e.g. my_string.rb), which has to be included in the environment.rb (require “my_string”). Here’s an example for three simple smilies:

# my_string.rb
module BBCodeizer
  class << self
    Tags[:smiley1] = [/\:\-?\)/, '<img title=":)" src="/images/emoticons/smile.png" alt="smile"/>']
    Tags[:smiley2] = [/\;\-?\)/, '<img title=";)" src="/images/emoticons/wink.png" alt="wink" />']
    Tags[:smiley3] = [/\:\-?\(/, '<img title=":(" src="/images/emoticons/sad.png" alt="sad" />']

    TagList += [:smiley1, :smiley2, :smiley3]
  end
end

Appendix: As you can see, i’ve modified the constants Tags and TagList which is at least not good style and throws a warning. To use proper code, you could change the bbcodeizer plugin constants to variables (using lower-case characters, e.g. tags and tag_list). Other possibility is to adjust the constants directly in the plugin.

The smiley shortcuts are now replaced by the according images in any text you pass bbcodeize (e.g.

bbcodeize 'Hi :) '

returns

'Hi <img title=":)" src="/images/emoticons/smile.png" alt="smile" />'

Dont forget to put some smilies in /images/emoticons Keywords: smiley, smileys, smilie, smilies, rails, bbcode, bbcodeizer, ruby, emoticon, emoticons

Move Wubi installation (Ubuntu on Windows) to a native Ubuntu system

There’s a tool called LVPM which could do the move, but there are sometimes problems with it. So I recommend to use a faster and safer way to do it – with the wubi-move-to-partition script:

  1. Boot into your Wubi installation.
  2. Open a shell and do a:
    wget "https://wiki.ubuntu.com/WubiGuide?action=AttachFile&do=get&target=wubi-move-to-partition"
  3. Install and run gparted:
    sudo apt-get install gparted
    sudo gparted
  4. Now create a swap partition (1x or better 2x the size of your memory) and an ext3 partition for your new ubuntu partition.
  5. Back in the shell, find out how the new partitions are called with:
    sudo fdisk -l
  6. Now start the move:
    sudo sh wubi-move-to-partition /dev/sdx1 /dev/sdx2
    (where /dev/sdx1 is your new ubuntu partition and /dev/sdx2 is the new swap partition you’ve just created with gparted)
  7. After the successful move, simply reboot your system. You should be able to boot into your new native ubuntu system.

If there are no problems with your new system, you might want to boot into windows to uninstall your wubi installation (Start Menu/Control Panel/Add or Remove Programs). It’s not needed any longer.
Keywords: transfer wubi, upgrade wubi, change wubi, native ubuntu, native linux, proper, clean, full, real, remove wubi

Smilies in Rails using RedCloth

There’s also a guide to use Smilies in Rails using BBCodeizer.

RedCloth doesn’t come with support for smilies, so i’ve added it for one of my projects.
You need to extend the RedCloth class. You could do this by creating a file in your /lib directory, which you have to include in your environment.rb. Here an example for three simple smilies:

class RedCloth
  def glyphs_smilies(text)
    text.gsub!(/\:\-?\)/, '<img src="/images/emoticons/smile.png" alt="smile" />')
    text.gsub!(/\;\-?\)/, '<img src="/images/emoticons/wink.png" alt="wink" />')
    text.gsub!(/\:\-?\(/, '<img src="/images/emoticons/sad.png" alt="sad" />')
  end
end

To include this new function in your views, write an helper, e.g. format_text in ApplicationHelper:

module ApplicationHelper
  def format_text(text)
    RedCloth.new(text).to_html(:textile, :glyphs_smilies)
  end
end

Now you could use it anywhere in your views, like

  <%= format_text ":)" %>

or

  <%= format_text @your_record.your_text %>

Of course, you have to put some smilies in /images/emoticons :)

Keywords: smiley, smileys, smilie, smilies, rails, textile, redcloth, ruby, emoticon, emoticons

Rails: routes and special characters like dots

Rails doesn’t seem to like dots and other special chars in its routes.
If you want to use URLs like http://www.domain.com/post/1/just_a_test.. logically the following route seems to be sensible:

map.connect '/post/:id/:title', :controller => 'forum', :action => 'show_post'

But rails won’t like the dots. Use a route like the following to allow a URL with special characters to be routed:

map.connect '/post/:id/:title', :controller => 'forum', :action => 'show_post', :requirements => { :title => /.*/ }

Keywords: dots, dot, no route matches, punkt, punkte, routes.rb, routing, route, rails, problem, won’t work

Sehnsucht nach Ruhe

Functional test for HTTP Basic Authentication in Rails 2

If you want to provide a username and password for a HTTP Basic Authentication in one of your functional tests, simply use the following:

def test_should_get_index
  @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password")
  get :index
  assert_response :success
  assert_not_nil assigns(:articles)
end

Keywords: rails test, functionals, authorization, basic http authentication, how to test


linkboost