--- /dev/null
+class AdminController < ApplicationController
+ def login
+ session[:user_id] = nil
+ if request.post?
+ user = User.authenticate(params[:name], params[:password])
+ if user
+ session[:user_id] = user.id
+ uri = session[:original_uri]
+ session[:original_uri] = nil
+ redirect_to uri || {:action => 'index'}
+ else
+ flash.now[:notice] = "Invalid user/password combination"
+ end
+ end
+ end
+
+ def logout
+ session[:user_id] = nil
+ flash[:notice] = "Logged out"
+ redirect_to(:action => "login")
+ end
+
+ def index
+ @total_orders = Order.count
+ end
+
+end
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
+ layout "store"
+ before_filter :authorize, :except => :login
helper :all # include all helpers, all the time
# See ActionController::RequestForgeryProtection for details
# Uncomment this to filter the contents of submitted sensitive data parameters
# from your application log (in this case, all fields with names like "password").
# filter_parameter_logging :password
+
+ protected
+ def authorize
+ unless User.find_by_id(session[:user_id])
+ session[:original_uri] = request.request_uri
+ flash[:notice] = "Please log in"
+ redirect_to :controller => 'admin', 'action' => 'login'
+ end
+ end
end
class StoreController < ApplicationController
+ before_filter :find_cart, :except => :empty_cart
+
def index
@products = Product.find_products_for_sale
- @cart = find_cart
+# @cart = find_cart
end
def add_to_cart
product = Product.find(params[:id])
- @cart = find_cart
+# @cart = find_cart
@current_item = @cart.add_product(product)
respond_to do |format|
format.js if request.xhr?
end
def checkout
- @cart = find_cart
+# @cart = find_cart
if @cart.items.empty?
redirect_to_index("Your cart is empty" )
else
end
def save_order
- @cart = find_cart
+# @cart = find_cart
@order = Order.new(params[:order])
# @order.add_line_items_from_cart(@cart)
@cart.items.each do |item|
end
+protected
+
+ # No authorization needed for the store
+ def authorize
+ end
+
private
def find_cart
- session[:cart] ||= Cart.new
+ @cart = (session[:cart] ||= Cart.new)
end
def redirect_to_index(msg = nil)
--- /dev/null
+class UsersController < ApplicationController
+ # GET /users
+ # GET /users.xml
+ def index
+ @users = User.find(:all, :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
+ flash[:notice] = "User #{@user.name} was successfully created."
+ format.html { redirect_to(:action => 'index') }
+ 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])
+ flash[:notice] = "User #{@user.name} was successfully updated."
+ format.html { redirect_to(:action => 'index') }
+ 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
+ flash[:notice] = "User #{@user.name} deleted"
+ @user.destroy
+ 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
--- /dev/null
+module AdminHelper
+end
--- /dev/null
+module UsersHelper
+end
--- /dev/null
+require 'digest/sha1'
+
+class User < ActiveRecord::Base
+ validates_presence_of :name
+ validates_uniqueness_of :name
+
+ attr_accessor :password_confirmation
+ validates_confirmation_of :password
+
+ validate :password_non_blank
+
+ def password
+ @password
+ end
+
+ def password=(passwd)
+ @password = passwd
+ return if passwd.blank?
+ create_new_salt
+ self.hashed_password = User.encrypted_password(self.password, self.salt)
+ end
+
+ def self.authenticate(name, password)
+ user = self.find_by_name(name)
+ if user
+ expected_password = encrypted_password(password, user.salt)
+ if user.hashed_password != expected_password
+ user = nil
+ end
+ end
+ user
+ end
+
+ def after_destroy
+ if User.count.zero?
+ raise "Can't delete last user"
+ end
+ end
+
+private
+
+ def password_non_blank
+ errors.add(:password, "Missing password" ) if hashed_password.blank?
+ end
+
+ def self.encrypted_password(password, salt)
+ string_to_hash = password + 'wibble' + salt
+ Digest::SHA1.hexdigest string_to_hash
+ end
+
+ def create_new_salt
+ self.salt = self.object_id.to_s + rand.to_s
+ end
+
+end
--- /dev/null
+
+<h1>Welcome, <%= User.find(session[:user_id]).name %></h1>
+It's <%= Time.now %>.
+We have <%= pluralize(@total_orders, "order" ) %>.
\ No newline at end of file
--- /dev/null
+
+<div class="depot-form">
+ <% form_tag do %>
+ <fieldset>
+ <legend>Please Log In</legend>
+ <div>
+ <label for="name">Name:</label>
+ <%= text_field_tag :name, params[:name] %>
+ </div>
+ <div>
+ <label for="password">Password:</label>
+ <%= password_field_tag :password, params[:password] %>
+ </div>
+ <div>
+ <%= submit_tag "Login" %>
+ </div>
+ </fieldset>
+ <% end %>
+</div>
\ No newline at end of file
--- /dev/null
+<h1>Admin#logout</h1>
+<p>Find me in app/views/admin/logout.html.erb</p>
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
- <title>Orders: <%= controller.action_name %></title>
- <%= stylesheet_link_tag 'scaffold' %>
-</head>
-<body>
-
-<p style="color: green"><%= flash[:notice] %></p>
-
-<%= yield %>
-
-</body>
-</html>
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
- <title>Products: <%= controller.action_name %></title>
- <%= stylesheet_link_tag 'scaffold', 'depot' %>
-</head>
-<body>
-
-<p style="color: green"><%= flash[:notice] %></p>
-
-<%= yield %>
-
-</body>
-</html>
</div>
<div id="columns">
<div id="side">
- <% hidden_div_if(@cart.items.empty?, :id => "cart") do %>
- <%= render(:partial => "cart" , :object => @cart) %>
- <% end %>
+ <% if @cart %>
+ <% hidden_div_if(@cart.items.empty?, :id => "cart") do %>
+ <%= render(:partial => "cart" , :object => @cart) %>
+ <% end %>
+ <% end %>
<a href="/">Home</a><br />
<a href="http://www..../faq">Questions</a><br />
<a href="http://www..../news">News</a><br />
<a href="http://www..../contact">Contact</a><br />
+
+ <% if session[:user_id] %>
+ <br />
+ <%= link_to 'Orders', :controller => 'orders' %><br />
+ <%= link_to 'Products', :controller => 'products' %><br />
+ <%= link_to 'Users', :controller => 'users' %><br />
+ <br />
+ <%= link_to 'Logout', :controller => 'admin', :action => 'logout' %>
+ <% end %>
+
</div>
<div id="main">
<% if flash[:notice] -%>
--- /dev/null
+<div class="depot-form">
+
+ <% form_for(@user) do |f| %>
+ <%= f.error_messages %>
+
+ <fieldset>
+ <legend>Update user details</legend>
+
+ <div>
+ <%= f.label :name %>:
+ <%= f.text_field :name, :size => 40 %>
+ </div>
+
+ <div>
+ <%= f.label :user_password, 'Password' %>:
+ <%= f.password_field :password, :size => 40 %>
+ </div>
+ <div>
+ <%= f.label :user_password_confirmation, 'Confirm' %>:
+ <%= f.password_field :password_confirmation, :size => 40 %>
+ </div>
+ <div>
+ <%= f.submit "Update" %>
+ </div>
+
+ </fieldset>
+ <% end %>
+
+ <%= link_to 'Show', @user %> |
+ <%= link_to 'Back', users_path %>
+</div>
--- /dev/null
+<h1>Listing users</h1>
+
+<table>
+ <tr>
+ <th>Name</th>
+ </tr>
+
+<% for user in @users %>
+ <tr>
+ <td><%=h user.name %></td>
+ <td><%= link_to 'Show', user %></td>
+ <td><%= link_to 'Edit', edit_user_path(user) %></td>
+ <td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New user', new_user_path %>
--- /dev/null
+<div class="depot-form">
+
+ <% form_for(@user) do |f| %>
+ <%= f.error_messages %>
+
+ <fieldset>
+ <legend>Enter user details</legend>
+
+ <div>
+ <%= f.label :name %>:
+ <%= f.text_field :name, :size => 40 %>
+ </div>
+
+ <div>
+ <%= f.label :user_password, 'Password' %>:
+ <%= f.password_field :password, :size => 40 %>
+ </div>
+ <div>
+ <%= f.label :user_password_confirmation, 'Confirm' %>:
+ <%= f.password_field :password_confirmation, :size => 40 %>
+ </div>
+ <div>
+ <%= f.submit "Create" %>
+ </div>
+
+ </fieldset>
+ <% end %>
+
+ <%= link_to 'Back', users_path %>
+</div>
--- /dev/null
+<p>
+ <b>Name:</b>
+ <%=h @user.name %>
+</p>
+
+<p>
+ <b>Hashed password:</b>
+ <%=h @user.hashed_password %>
+</p>
+
+<p>
+ <b>Salt:</b>
+ <%=h @user.salt %>
+</p>
+
+
+<%= link_to 'Edit', edit_user_path(@user) %> |
+<%= link_to 'Back', users_path %>
ActionController::Routing::Routes.draw do |map|
+ map.resources :users
+
+ map.resources :line_items
+
+ map.resources :orders
+
map.resources :products
# The priority is based upon order of creation: first created -> highest priority.
--- /dev/null
+class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table :users do |t|
+ t.string :name
+ t.string :hashed_password
+ t.string :salt
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :users
+ end
+end
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20090304153613) do
+ActiveRecord::Schema.define(:version => 20090311105014) do
create_table "line_items", :force => true do |t|
t.integer "product_id", :null => false
add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
+ create_table "users", :force => true do |t|
+ t.string "name"
+ t.string "hashed_password"
+ t.string "salt"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
end
--- /dev/null
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+one:
+ name: MyString
+ hashed_password: MyString
+ salt: MyString
+
+two:
+ name: MyString
+ hashed_password: MyString
+ salt: MyString
--- /dev/null
+require 'test_helper'
+
+class AdminControllerTest < ActionController::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
--- /dev/null
+require 'test_helper'
+
+class UsersControllerTest < ActionController::TestCase
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:users)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create user" do
+ assert_difference('User.count') do
+ post :create, :user => { }
+ end
+
+ assert_redirected_to user_path(assigns(:user))
+ end
+
+ test "should show user" do
+ get :show, :id => users(:one).id
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, :id => users(:one).id
+ assert_response :success
+ end
+
+ test "should update user" do
+ put :update, :id => users(:one).id, :user => { }
+ assert_redirected_to user_path(assigns(:user))
+ end
+
+ test "should destroy user" do
+ assert_difference('User.count', -1) do
+ delete :destroy, :id => users(:one).id
+ end
+
+ assert_redirected_to users_path
+ end
+end
--- /dev/null
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end