Screencast: attr_accessible dynamisch setzen

Um Attribute eines Datenbank-Objekts zu schützen, kann in Rails auf attr_accessible zurückgegriffen werden. Damit wird verhindert, dass bei Mass Assingments bestimmte Attribute nicht verändert werden. Wenn der Zugriff/die Veränderung auf Basis von Zugriffsrechten erfolgen soll, muss attr_accessible dynamisch gesetzt werden. Wie dies funktioniert, zeigt Ryan in diesem Screencast

 

Download:

Download(16 MB, 9:12)
Alternativer Download für iPod & Apple TV(15 MB, 9:12)

 

Resourcen:

 

Quellcode:

[ruby]
# config/initializers/accessible_attributes.rb
class ActiveRecord::Base
attr_accessible
attr_accessor :accessible

private

def mass_assignment_authorizer
if accessible == :all
self.class.protected_attributes
else
super + (accessible || [])
end
end
end

# models/article.rb
class Article < ActiveRecord::Base
attr_accessible :name, :content
end

# articles_controller.rb
def create
@article = Article.new
@article.accessible = :all if admin?
@article.attributes = params[:article]
if @article.save
flash[:notice] = "Successfully created article."
redirect_to @article
else
render :action => ’new‘
end
end

def update
@article = Article.find(params[:id])
@article.accessible = :all if admin?
if @article.update_attributes(params[:article])
flash[:notice] = "Successfully updated article."
redirect_to @article
else
render :action => ‚edit‘
end
end
[/ruby]

Phusion Passenger 3 veröffentlicht

Phusion Passenger ist seit gestern in der dritten Version verügbar. Die neue Version bringt einige Neuerungen mit, die die Arbeit mit Rails wieder vereinfachen bzw. verbessern.

Dies sind die Verbeserungen/Neuerungen in Passenger 3:

  • Bis zu 55% mehr Geschwindigkeit
  • Die Stabilität wurde weiter verbessert
  • Selfhealing ist ein neues Feature um abgestüzte Hauptprozesse wieder zu beleben
  • Standalone-Version um Passenger während der Entwicklung oder hinter Proxies zu benutzen
  • Limitierungen aus der vorherigen Version wurden entfernt
  • Neue Features wurden hinzugefügt
  • Passenger kann nun mit unterschiedlichen Ruby Versionen betrieben werden

Weitere Details zu dem Release inklusive Details zu den einzelen Erneuerungen gibt es im Phusion-Blog: http://blog.phusion.nl/2010/10/18/phusion-passenger-3-0-0-final-released/

Securtiy Update Für Rails 2.3.9 und 3.0

Für die aktuellen Rails Versionen der Reihe 2.3 und 3.0 wurde heute ein Securtiy-Update veröffentlicht. Die Schwachstelle kann unter bestimmten Umständen von Angreifern ausgenutzt werden, um eigenen Code in die Applikation einzuschleusen.

Die betroffenen Versionen sind 2.3.9 und 3.0.0. Die vorherigen Versionen sind ausgeschlossen.

Es gibt zwei Möglichkeiten bestehende Applikationen zu aktualisieren:

  1. Ein Update über die bekannten Wege via gem:
    [bash]
    gem update rails
    [/bash]
  2. Ein Update durch einen Patch (Falls ein Update über gem nicht Möglich sein sollte)
    Die Patches sind unter folgenden Links Verfügbar:

Mehr Details gibt unter folgendem Link http://weblog.rubyonrails.org/2010/10/15/security-vulnerability-in-nested-attributes-code-in-ruby-on-rails-2-3-9-and-3-0-0?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+RidingRails+%28Riding+Rails%29

Screencast: OmniAuth Teil 2

Im zweiten Teil der OmniAuth-Screencasts zeigt Ryan wie OmniAuth in Device integriert werden kann und wie neue Benutzer incl. Validierung angelegt werden können.

 

Download:

Download(25.6 MB, 15:59)
Alternativer Download für iPod & Apple TV(23.9 MB, 15:59)

 

Resourcen:

 

Quellcode:

[bash]
bundle update
rails g controller registrations
rails g devise:views
[/bash]

[ruby]
# Gemfile
gem ‚mongrel‘, ‚1.2.0.pre2‘

# config/initializers/omniauth.rbb
require ‚openid/store/filesystem‘
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ‚CONSUMER_KEY‘, ‚CONSUMER_SECRET‘
provider :open_id, OpenID::Store::Filesystem.new(‚/tmp‘)
end

# authentications_controller.rb
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth[‚provider‘], omniauth[‚uid‘])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth[‚provider‘], :uid => omniauth[‚uid‘])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except(‚extra‘)
redirect_to new_user_registration_url
end
end
end

# models/user.rb
def apply_omniauth(omniauth)
self.email = omniauth[‚user_info‘][‚email‘] if email.blank?
authentications.build(:provider => omniauth[‚provider‘], :uid => omniauth[‚uid‘])
end

def password_required?
(authentications.empty? || !password.blank?) && super
end

# routes.rb
devise_for :users, :controllers => {:registrations => ‚registrations‘}

# registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless @user.new_record?
end

private

def build_resource(*args)
super
if session[:omniauth]
@user.apply_omniauth(session[:omniauth])
@user.valid?
end
end
end

# models/authentication.rb
def provider_name
if provider == ‚open_id‘
"OpenID"
else
provider.titleize
end
end
[/ruby]

Screencast: OmniAuth Teil 1

Die traditionelle Authentifizierung mit einem eigenem System wird immer mehr zur einer Ausnahme. Moderne Webapplikationen bieten daher die Anmeldung über bestehende Dienste wie OpenID, Twitter, Facebook und/oder OAuth an. OmniAuth ist ein Plugin das in Rails-App für diesen Zweck eingesetzt werden kann. Ryan zeigt in im ersten Teil wie es in Devise integriert werden kann.

 

Download:

Download(25.6 MB, 10:52)
Alternativer Download für iPod & Apple TV(22.3 MB, 10:52)

 

Resourcen:

 

Quellcode:

[bash]
bundle install
rails g nifty:scaffold authentication user_id:integer provider:string uid:string index create destroy
rake db:migrate
[/bash]

[ruby]
# Gemfile
gem ‚omniauth‘

# models/user.rb
has_many :authentications

# models/authentication.rb
belongs_to :user

# authentications_controller.rb
def index
@authentications = current_user.authentications if current_user
end

def create
auth = request.env["rack.auth"]
current_user.authentications.find_or_create_by_provider_and_uid(auth[‚provider‘], auth[‚uid‘])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
end

def destroy
@authentication = current_user.authentications.find(params[:id])
@authentication.destroy
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
[/ruby]

[html]
<!– authentications/index.html.erb –>
<% title "Sign In" %>

<% if @authentications %>
<% unless @authentications.empty? %>
<p><strong>You can sign in to this account using:</strong></p>
<div class="authentications">
<% for authentication in @authentications %>
<div class="authentication">
<%= image_tag "#{authentication.provider}_32.png", :size => "32×32" %>
<div class="provider"><%= authentication.provider.titleize %></div>
<div class="uid"><%= authentication.uid %></div>
<%= link_to "X", authentication, :confirm => ‚Are you sure you want to remove this authentication option?‘, :method => :delete, :class => "remove" %>
</div>
<% end %>
<div class="clear"></div>
</div>
<% end %>
<p><strong>Add another service to sign in with:</strong></p>
<% else %>
<p><strong>Sign in through one of these services:</strong></p>
<% end %>

<a href="/auth/twitter" class="auth_provider">
<%= image_tag "twitter_64.png", :size => "64×64", :alt => "Twitter" %>
Twitter
</a>
<a href="/auth/facebook" class="auth_provider">
<%= image_tag "facebook_64.png", :size => "64×64", :alt => "Facebook" %>
Facebook
</a>
<a href="/auth/google_apps" class="auth_provider">
<%= image_tag "google_64.png", :size => "64×64", :alt => "Google" %>
Google
</a>
<a href="/auth/open_id" class="auth_provider">
<%= image_tag "openid_64.png", :size => "64×64", :alt => "OpenID" %>
OpenID
</a>
<div class="clear"></div>
[/html]

[css]
// application.css
.authentications {
margin-bottom: 30px;
}

.authentication {
width: 130px;
float: left;
background-color: #EEE;
border: solid 1px #999;
padding: 5px 10px;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
position: relative;
margin-right: 10px;
}

.authentication .remove {
text-decoration: none;
position: absolute;
top: 3px;
right: 3px;
color: #333;
padding: 2px 4px;
font-size: 10px;
}

.authentication .remove:hover {
color: #CCC;
background-color: #777;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}

.authentication img {
float: left;
margin-right: 10px;
}

.authentication .provider {
font-weight: bold;
}

.authentication .uid {
color: #666;
font-size: 11px;
}

.auth_provider img {
display: block;
}

.auth_provider {
float: left;
text-decoration: none;
margin-right: 20px;
text-align: center;
margin-bottom: 10px;
}
[/css]

Screencast: Simple Form

Simple Form ist ein gem zur Unterstützung bei der Entwicklung von Formularen. In diesem Screencast gibt Ryan einen Überblick wie es eingesetzt werden kann.

 

Download:

Download(14.7 MB, 7:50)
Alternativer Download für iPod & Apple TV(13.7 MB, 7:50)

 

Resourcen:

 

Quellcode:

[bash]
bundle_install
rails g simple_form:install
[/bash]

[html]
<%= simple_form_for @product do |f| %>
<%= f.error_messages %>
<%= f.input :name %>
<%= f.input :price, :hint => "prices should be in USD" %>
<%= f.input :released_on %>
<%= f.association :category, :include_blank => false %>
<%= f.input :rating, :collection => 1..5, :as => :radio %>
<%= f.input :discontinued %>
<%= f.button :submit %>
<% end %>
[/html]

[css]
/* stylesheets/application.css */
.simple_form label {
float: left;
width: 100px;
text-align: right;
margin: 2px 10px;
}

.simple_form div.input {
margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type=’submit‘] {
margin-left: 120px;
}

.simple_form div.boolean label, .simple_form label.collection_radio {
float: none;
margin: 0;
}

.simple_form label.collection_radio {
margin-right: 10px;
margin-left: 2px;
}

.simple_form .error {
clear: left;
margin-left: 120px;
font-size: 12px;
color: #D00;
display: block;
}

.simple_form .hint {
clear: left;
margin-left: 120px;
font-size: 12px;
color: #555;
display: block;
font-style: italic;
}
[/css]