Desenvolvimento web com Ruby on Rails (parte 6)

964 views
863 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
964
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
15
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Desenvolvimento web com Ruby on Rails (parte 6)

  1. 1. Desenvolvimento Web com Ruby on Rails João Lucas Pereira de Santana gtalk | linkedin | twitter: jlucasps
  2. 2. Devise @jlucasps Solução flexível para autenticação de usuários Segue o padrão MVC Totalmente integrada com o Rails Permite várias roles autenticadas ao mesmo tempo (user, admin, member) Baseada em conceitos de módulos
  3. 3. ● Database Authenticatable ○ Criptografar a senha e armazenar em banco de dados ○ Auntenticação pode ser feita via POST ou HTTP Basic Authentication Devise @jlucasps
  4. 4. ● Token Authenticatable ○ Autenticar o usuário baseado em um token de acesso ○ Token pode ser enviado via query string ou HTTP Basic Authentication Devise @jlucasps
  5. 5. Devise @jlucasps ● Omniauthable ○ Framework de autenticação compatível com diversos providers (facebook, twitter, openId, google, github), além dos tradicionais username e password
  6. 6. Devise @jlucasps ● Confirmable ○ Enviar email com as instruções de confirmação de cadastro ● Recoverable ○ Alterar password do usuário e enviar instruções de alteração
  7. 7. Devise @jlucasps ● Registerable ○ Permite cadastar usuários para utilizarem uma aplicação ○ Editar as informações de cadastro do usuário ○ Excluir o cadastro
  8. 8. Devise @jlucasps ● Rememberable ○ Mecanimo para salvar cookies e permitir manter usuário autenticado na aplicação ● Trackable ○ Registrar quantidade de acessos, hora do acesso e IP de origem
  9. 9. Devise @jlucasps ● Timeoutable ○ Expirar a sessão caso o usuário fique um período inativo ● Validatable ○ Validação de email e password ○ Mecanismo opcional e customizável
  10. 10. Devise @jlucasps ● Lockable ○ Bloquear a conta do usuário caso haja um certo número de tentativas frustradas de acesso ○ Desbloqueio pode ser feito via email ou após um período de tempo
  11. 11. Devise @jlucasps # https://github.com/plataformatec/devise # Flexible authentication solution for Rails with Warden gem 'devise' Atualizar Gemfile Atualizar config/environments/development.rb config.action_mailer.default_url_options = { :host => 'localhost:3000' }
  12. 12. MailCatcher @jlucasps # https://github.com/sj26/mailcatcher # Catches mail and serves it through a dream. gem 'mailcatcher' Adicionar MailCatcher ao Gemfile Atualizar config/environments/development.rb config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => "localhost", : port => 1025 } jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ mailcatcher Starting MailCatcher ==> smtp://127.0.0.1:1025 ==> http://127.0.0.1:1080 *** MailCatcher runs as a daemon by default. Go to the web interface to quit.
  13. 13. Devise @jlucasps Após adicionar Devise ao Gemfile, execute o generator jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ rails g devise: install create config/initializers/devise.rb create config/locales/devise.en.yml =========================================== ==================== Some setup you must do manually if you haven't yet: ....
  14. 14. Devise @jlucasps <!DOCTYPE html> <html> <head> <title>FirstApp</title> <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> </head> <body> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= render :partial => 'shared/menu_top' %> <div class="container-fluid"> <div class="row-fluid"> <%= yield :sidebar %> <%= yield %> </div> <%= render :partial => 'shared/footer' %> </div> </body> </html> Configurar /app/views/layouts/application.html.erb
  15. 15. Devise @jlucasps jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ rails g devise User invoke active_record create db/migrate/20130619172147_add_devise_to_users.rb insert app/models/user.rb route devise_for :users Adicionar Devise a algum model Configurar Migration gerada e executá-la jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ rake db:migrate == AddDeviseToUsers: migrating =============================================== -- change_table(:users) -> 0.0590s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0007s == AddDeviseToUsers: migrated (0.0600s) ======================================
  16. 16. Devise @jlucasps class ApplicationController < ActionController::Base protect_from_forgery before_filter :authenticate_user! end Configurar ApplicationController Configurar arquivo /config/initializers/devise.rb # ==> Scopes configuration # Turn scoped views on. Before rendering "sessions/new", it will first check for # "users/sessions/new". It's turned off by default because it's slower if you # are using only default views. config.scoped_views = true
  17. 17. Devise @jlucasps user_signed_in? current_user user_session Métodos helpers gerados pelo Devise Caso o model seja Member before_filter :authenticate_member! member_signed_in? current_member member_session
  18. 18. Devise @jlucasps jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ rails generate devise:views users invoke Devise::Generators::SharedViewsGenerator create app/views/users/shared create app/views/users/shared/_links.erb invoke form_for create app/views/users/confirmations create app/views/users/confirmations/new.html.erb create app/views/users/passwords create app/views/users/passwords/edit.html.erb Customizar as views utilizadas pelo Devise
  19. 19. Devise @jlucasps class WelcomeController < ApplicationController before_filter :authenticate_user!, :except => [:index, :about, :contact] def index end def black render :layout => 'application_black' end def about end def contact end end Caso queira liberar acesso para actions do WelcomeController
  20. 20. Devise @jlucasps <div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar-inner"> <div class="container-fluid"> <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <%= link_to "Project name", index_path, :class => "brand" %> <div class="nav-collapse collapse"> <p class="navbar-text pull-right"> <% if user_signed_in? %> Logged in as <%= link_to current_user.name edit_user_registration_path(current_user), : class => "navbar-link" %> <% else %> <%= link_to "login", new_user_session_path, :class => "btn" %> <% end %> </p> <ul class="nav"> <li class="active"><%= link_to "Home", index_path %></li> <li><%= link_to "About", about_path %></li> <li><%= link_to "Contact", contact_path %></li> </ul> </div><!--/.nav-collapse --> </div> </div> </div> Exibir link para login e usuário logado: /app/views/shared/_menu_top.html.erb
  21. 21. Devise @jlucasps <h2>Sign up</h2> <%= form_for(resource, :as => resource_name, :url => registration_path (resource_name)) do |f| %> <%= devise_error_messages! %> <div><%= f.label :name %><br /> <%= f.text_field :name, :autofocus => true %></div> <div><%= f.label :email %><br /> <%= f.email_field :email %></div> <div><%= f.label :password %><br /> <%= f.password_field :password %></div> <div><%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation %></div> <div><%= f.submit "Sign up" %></div> <% end %> <%= render "users/shared/links" %> Alterar tela de cadastro de usuários: /app/views/users/registrations/new.html.erb
  22. 22. Devise @jlucasps RSpec.configure do |config| # ## Mock Framework # # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: # # config.mock_with :mocha # config.mock_with :flexmock # config.mock_with :rr config.include Capybara::DSL config.include Devise::TestHelpers, :type => :controller config.include Rails.application.routes.url_helpers # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures #config.fixture_path = "#{::Rails.root}/spec/fixtures" Testes automatizados com Devise: /spec/spec_helper.rb
  23. 23. Devise @jlucasps include Warden::Test::Helpers def create_logged_in_user(user_sym) user = FactoryGirl.find_or_create(user_sym) login_as(user, scope: :user) user end class ActiveRecord::Base mattr_accessor :shared_connection @@shared_connection = nil def self.connection @@shared_connection || retrieve_connection end end ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection Devise support /spec/support/devise.rb
  24. 24. FactoryGirl @jlucasps # Factory_girl is a fixtures replacement with a straightforward definition syntax # https://github.com/thoughtbot/factory_girl_rails gem 'factory_girl_rails', "~> 4.0" Adicionar factory_girl ao Gemfile Importar factory_girl no spec_helper # This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'rspec/autorun' require 'factory_girl' require 'factory_girl_patch' require 'capybara/rails' require 'capybara/rspec' FactoryGirl.register_strategy(:find_or_create, FactoryGirlPatch)
  25. 25. FactoryGirl @jlucasps FactoryGirl.define do factory :user_bart, :class => User do name "Bart Simpson" email "bart@simpson.com" password "dirty_boy" password_confirmation "dirty_boy" encrypted_password BCrypt::Password.create("dirty_boy", :cost => 10) end factory :user_lisa, :class => User do name "Lisa Simpson" email "lisa@simpson.com" password "smart_girl" password_confirmation "smart_girl" encrypted_password BCrypt::Password.create("smart_girl", :cost => 10) end end Criar factories
  26. 26. FactoryGirl @jlucasps class FactoryGirlPatch def association(runner) runner.run end def result(evaluation) evaluation.object.tap do |instance| evaluation.notify(:after_build, instance) evaluation.notify(:before_create, instance) saved_object = instance.class.where(instance.attributes.except("id", "created_at", "updated_at")).first if saved_object.present? instance.id = saved_object.id instance.created_at = saved_object.created_at if instance.respond_to?(:created_at) instance.updated_at = saved_object.updated_at if instance.respond_to?(:updated_at) else evaluation.create(instance) evaluation.notify(:after_create, instance) end end end end Estratégia find_or_create: /lib/factory_girl_patch.rb
  27. 27. Devise @jlucasps require 'spec_helper' describe UsersController do let(:user_bart) { FactoryGirl.find_or_create(:user_bart)} before(:each) do sign_in user_bart end describe "GET index" do it "assigns @users" do saved_users = [FactoryGirl.find_or_create(:user_bart), FactoryGirl.find_or_create(: user_lisa)] get :index assigns(:users).should eq(saved_users) end end end Testes no controller /spec/controllers/users_controller_spec.rb
  28. 28. Devise @jlucasps Testes no controller /spec/controllers/users_controller_spec.rb jlucasps@lotus:/media/first_app$ rspec spec/controllers/users_controller_spec.rb . Finished in 0.331 seconds 1 example, 0 failures Randomized with seed 5290
  29. 29. Desenvolvimento Web com Ruby on Rails João Lucas Pereira de Santana gtalk | linkedin | twitter: jlucasps Obrigado!

×