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


linkboost