29
Desenvolvimento Web com Ruby on Rails João Lucas Pereira de Santana gtalk | linkedin | twitter: jlucasps

Desenvolvimento web com Ruby on Rails (parte 6)

Embed Size (px)

Citation preview

Page 1: Desenvolvimento web com Ruby on Rails (parte 6)

Desenvolvimento Web com Ruby on

Rails

João Lucas Pereira de Santanagtalk | linkedin | twitter: jlucasps

Page 2: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 3: Desenvolvimento web com Ruby on Rails (parte 6)

● Database Authenticatable

○ Criptografar a senha e armazenar em

banco de dados

○ Auntenticação pode ser feita via POST ou

HTTP Basic Authentication

Devise

@jlucasps

Page 4: Desenvolvimento web com Ruby on Rails (parte 6)

● 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

Page 5: Desenvolvimento web com Ruby on Rails (parte 6)

Devise

@jlucasps

● Omniauthable

○ Framework de autenticação compatível

com diversos providers (facebook, twitter,

openId, google, github), além dos

tradicionais username e password

Page 6: Desenvolvimento web com Ruby on Rails (parte 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

Page 7: Desenvolvimento web com Ruby on Rails (parte 6)

Devise

@jlucasps

● Registerable

○ Permite cadastar usuários para utilizarem

uma aplicação

○ Editar as informações de cadastro do

usuário

○ Excluir o cadastro

Page 8: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 9: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 10: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 11: Desenvolvimento web com Ruby on Rails (parte 6)

Devise

@jlucasps

# https://github.com/plataformatec/devise# Flexible authentication solution for Rails with Wardengem 'devise'

Atualizar Gemfile

Atualizar config/environments/development.rb

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

Page 12: Desenvolvimento web com Ruby on Rails (parte 6)

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.rbconfig.action_mailer.delivery_method = :smtpconfig.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }

jlucasps@lotus:/media/truecrypt1/handsonrails/first_app$ mailcatcherStarting 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.

Page 13: Desenvolvimento web com Ruby on Rails (parte 6)

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:....

Page 14: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 15: Desenvolvimento web com Ruby on Rails (parte 6)

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á-lajlucasps@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) ======================================

Page 16: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 17: Desenvolvimento web com Ruby on Rails (parte 6)

Devise

@jlucasps

user_signed_in?current_useruser_session

Métodos helpers gerados pelo Devise

Caso o model seja Member

before_filter :authenticate_member!member_signed_in?current_membermember_session

Page 18: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 19: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 20: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 21: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 22: Desenvolvimento web com Ruby on Rails (parte 6)

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

Page 23: Desenvolvimento web com Ruby on Rails (parte 6)

Devise

@jlucasps

include Warden::Test::Helpersdef create_logged_in_user(user_sym) user = FactoryGirl.find_or_create(user_sym) login_as(user, scope: :user) userend class ActiveRecord::Base mattr_accessor :shared_connection @@shared_connection = nil def self.connection @@shared_connection || retrieve_connection endendActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

Devise support /spec/support/devise.rb

Page 24: Desenvolvimento web com Ruby on Rails (parte 6)

FactoryGirl

@jlucasps

# Factory_girl is a fixtures replacement with a straightforward definition syntax# https://github.com/thoughtbot/factory_girl_railsgem '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)

Page 25: Desenvolvimento web com Ruby on Rails (parte 6)

FactoryGirl

@jlucasps

FactoryGirl.define do factory :user_bart, :class => User do name "Bart Simpson" email "[email protected]" 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 "[email protected]" password "smart_girl" password_confirmation "smart_girl" encrypted_password BCrypt::Password.create("smart_girl", :cost => 10) endend

Criar factories

Page 26: Desenvolvimento web com Ruby on Rails (parte 6)

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 endend

Estratégia find_or_create: /lib/factory_girl_patch.rb

Page 27: Desenvolvimento web com Ruby on Rails (parte 6)

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 endend

Testes no controller /spec/controllers/users_controller_spec.rb

Page 28: Desenvolvimento web com Ruby on Rails (parte 6)

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 seconds1 example, 0 failures Randomized with seed 5290

Page 29: Desenvolvimento web com Ruby on Rails (parte 6)

Desenvolvimento Web com Ruby on

Rails

João Lucas Pereira de Santanagtalk | linkedin | twitter: jlucasps

Obrigado!