13.5 Playtime 13.3 Iteration H3: Limiting Access
edit app/models/user.rb
require 'digest/sha1'
class User < ActiveRecord::Base
validates :name, :presence => true, :uniqueness => true
validates :password, :confirmation => true
attr_accessor :password_confirmation
attr_reader :password
validate :password_must_be_present
class << self
def authenticate(name, password)
if user = find_by_name(name)
if user.hashed_password == encrypt_password(password, user.salt)
user
end
end
end
def encrypt_password(password, salt)
Digest::SHA1.hexdigest(password + "wibble" + salt)
end
end
# 'password' is a virtual attribute
def password=(password)
@password = password
if password.present?
self.salt = generate_salt
self.hashed_password = self.class.encrypt_password(password, salt)
end
end
after_destroy :ensure_an_admin_remains
def ensure_an_admin_remains
if User.count.zero?
raise "Can't delete last user"
end
end
private
def password_must_be_present
errors.add(:password, "Missing password") unless hashed_password.present?
end
def generate_salt
self.salt = self.object_id.to_s + rand.to_s
end
end
edit app/controllers/users_controller.rb
class UsersController < ApplicationController
# GET /users
# GET /users.xml
def index
@users = User.order(:name)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
# GET /users/1
# GET /users/1.xml
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/new
# GET /users/new.xml
def new
@user = User.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/1/edit
def edit
@user = User.find(params[:id])
end
# POST /users
# POST /users.xml
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to(users_url,
:notice => "User #{@user.name} was successfully created.") }
format.xml { render :xml => @user,
:status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors,
:status => :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.xml
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
format.html { redirect_to(users_url,
:notice => "User #{@user.name} was successfully updated.") }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors,
:status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
@user = User.find(params[:id])
begin
@user.destroy
flash[:notice] = "User #{@user.name} deleted"
rescue Exception => e
flash[:notice] = e.message
end
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
end