ЗАДАЧА Е: АДМИНИСТРИРОВАНИЕ Выполнили: Асадуллина А.Ф., Алексеева Е. А
Шаг Е1: добавление пользователей depot> ruby script/generate model user Создаём модель «Пользователь»
Шаг Е1: добавление пользователей...\rails_apps\depot\db\migrate\007_create_users.rb class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.column :name, :string t.column :hashed_password, :string t.column :salt, :string end def self.down drop_table :users end Создадим миграцию и применим её к базе данных.
Шаг Е1: добавление пользователей depot> rake db:migrate Запустим миграцию.
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb class User < ActiveRecord::Base validates_presence_of :name, :password, :password_confirmation validates_uniqueness_of :name validates_length_of :password, :minimum => 5, :message => "should be at least 5 characters long" attr_accessor :password_confirmation validates_confirmation_of :password end Добавим функции проверки.
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb private def self.encrypted_password(password, salt) string_to_hash = password + "wibble" + salt Digest::SHA1.hexdigest(string_to_hash) end Создаём хэшированный пароль.
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb require 'digest/sha1' class User < ActiveRecord::Base #… end Подключаем библиотеку digest/sha1
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb def create_new_salt self.salt = self.object_id.to_s + rand.to_s end Создадим строку зашумления для хэширования пароля.
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb def end def = pwd create_new_salt self.hashed_password = User.encrypted_password(self.password, self.salt) end Автоматически создаем хэшированную версию только что введенного открытым текстом нового пароля.
Шаг Е1: добавление пользователей...\rails_apps\depot\app\models\user.rb 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 user end Создадим метод для аутентификации пользователей.
Шаг Е1: администрирование пользователей depot> ruby script/generate controller Login add_user login logout delete_user list_users Создадим контроллер Login и методы add_user, login, logout, delete_user и list_users в нём.
Шаг Е1: администрирование пользователей...\rails_apps\depot\app\controllers\login_controller.rb class LoginController < ApplicationController layout "admin" def = User.new(params[:user]) if request.post? flash[:notice] = "User = User.new end #... Создадим метод «Добавить Пользователя»
Шаг Е1: администрирование пользователей...\rails_apps\depot\app\views\login\add_user.rhtml Enter User Details Name: 40 %> Password: 40 %> Confirm: 40 %> "submit" %> Шаблон формы регистрации пользователя.
Шаг Е1: администрирование пользователей Переходим по ссылке и проверяем, что получилось.
Шаг Е2: авторизация Что означает установка системы авторизации для администраторов нашего магазина? Нам нужно предоставить форму, позволяющую им вводить свои имена пользователей и пароли. Как только они пройдут авторизацию, мы должны каким-то образом зарегистрировать этот факт на время существования сессии (пока они не выйдут из административной зоны). Нам нужно ограничить доступ к административной части приложения, разрешая его только тем людям, кто вошел, чтобы управлять магазином.
Шаг Е2: авторизация...\rails_apps\depot\app\controllers\login_controller.rb def login session[:user_id] = nil if request.post? user = User.authenticate(params[:name], params[:password]) if user session[:user_id] = user.id redirect_to(:action => "index" ) else flash[:notice] = "Invalid user/password combination" end Создаём контроллер авторизации.
Шаг Е2: авторизация...\rails_apps\depot\app\views\login\login.rhtml Please Log In Name: Password: Шаблон формы для авторизации.
Шаг Е2: авторизация Создадим файл index.rhtml в каталоге...\rails_apps\depot\app\views\login\ Welcome It's. We have. Представление страницы «index» - первой страницы, доступной администраторам после авторизации.
Шаг Е2: авторизация...\rails_apps\depot\app\controllers\login_controller.rb def = Order.count end Действие «index» установит количество заказов.
Шаг Е2: авторизация Теперь мы можем авторизоваться в качестве администратора. Переходим по ссылке и проверяем, что получилось.
Шаг Е3: Ограничение доступа Необходимо закрыть доступ людям, непрошедшим авторизацию и не имеющим прав администратора, к административным страницам нашего сайта. Для этого мы используем фильтры. Фильтры Rails позволяют перехватывать вызовы методов действий, добавляя свою собственную обработку перед тем, как методы будут реально вызваны, после окончания их работы или и в том и другом случае. Сейчас мы воспользуемся фильтром до вызова, чтобы перехватить все вызовы действий находящихся в нашем контроллере admin
Шаг Е3: Ограничение доступа Проверка производится перехватчиком по значению session[:user_id] Если оно установлено и соответствует пользователю, зарегистрированному в бд, то приложение знает, что в систему вошел администратор, и вызов можно задействовать. Если же значение не установлено, перехватчик осуществляет переадресацию на страницу авторизации.
Шаг Е3: Ограничение доступа Поместим этот метод в родительский класс всех контроллеров ApplicationController, который находится в app/controllers/application.rb class ApplicationController < ActionController::Base private def authorize unless User.find_by_id(session[:user_id]) flash[:notice] = "Please log in" redirect_to(:controller => "login", :action => "login") end
Шаг Е3: Ограничение доступа Так как мы уже регистрировались, нам необходимо удалить информацию о текущей сессии. depot> rake db:sessions:clear Теперь мы можем перейти по адресу: Фильтр заблокирует и перенаправит нас на страницу авторизации.
Шаг Е3: Ограничение доступа Для использования метод вызывается перед всеми действиями административного контроллера при помощи одной строки e в /app/controllers/admin_controller.rb before_filter :authoriz Так же внесем изменения в контроллер входа в систему /app/controllers/login_controller.rb : before_filter :authorize, :except => :login
Шаг Е4: Боковая панель и расширение административных функций. Создадим боковую панель в файле app/views/layouts/admin.rhtml
Шаг Е4: Боковая панель и расширение административных функций. Добавим функцию вывода списка пользователей к контроллеру авторизации в app/controllers/login_controller.rb def = User.find(:all) end
Шаг Е4: Боковая панель и расширение административных функций. Список будет отображаться при помощи шаблона app/views/login/list_users.rhtml Добавим в него ссылку на действие delete_user к каждой строке рядом с именем каждого пользователя в списке. Administrators 'login', :action => 'delete_user', :id => user}, { # html options :method => :post, :confirm => "Really delete #{user.name}?" } %>
Шаг Е4: Боковая панель и расширение административных функций. Удаление пользователя происходит по номеру id. При этом необходима проверка, что запрос отправлен с использованием POST. Необходима проверка на последнего пользователя. Удаление пользователя будет происходить в процессе транзакции базы данных. Откат будет сделан, если в базе не осталось ни одного пользователя.
Шаг Е4: Боковая панель и расширение административных функций. Напишем функцию отката в app/models/user.rb def after_destroy if User.count.zero? raise "Can't delete last user" end
Шаг Е4: Боковая панель и расширение административных функций. Запишем функцию удаления пользователя в файл /app/controllers/login_controller.rb def delete_user id = params[:id] if id && user = User.find(id) begin user.safe_delete flash[:notice] = "User #{user.name} deleted" rescue Exception => e flash[:notice] = e.message end redirect_to(:action => :list_users) end
Шаг Е4: Боковая панель и расширение административных функций. Реализуем функцию выхода из системы. В файл app/controllers/login_controller.rb Добавим функцию def logout session[:user_id] = nil flash[:notice] = "Logged out" redirect_to(:action => "login" ) end
Вопросы E1-E2 В каком виде хранятся пароли администраторов в базе данных? Ответ: В виде хэша. Что делает строчка attr_accessor :password? Ответ: Генерирует 2 метода: читающий (password) и записывающий (password=). Записывающий метод воспринимает присвоения. Что делает ? Ответ: создаёт обыкновенный блок HTML Где хранятся сведения о том, что администратор прошёл авторизацию? Ответ: В сессии.
Вопросы E3-E4 Что позволяет закрыть доступ людям, непрошедшим авторизацию и не имеющим прав администратора, к административным страницам нашего сайта? Ответ: Фильтры Rails. По какому значению происходит перехват в фильтре вызова? Ответ: session[:user_id]. По какому значению находят пользователя для удаления? Ответ: По id. Для чего нужна функция отката удаления пользователя? Ответ: Что бы в системе всегда был хотя бы один администратор.
Спасибо за внимание!