SlideShare a Scribd company logo
Desenvolvimento
Web com Ruby on
Rails
João Lucas Pereira de Santana
gtalk | linkedin | twitter: jlucasps
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
● Database Authenticatable
○ Criptografar a senha e armazenar em
banco de dados
○ Auntenticação pode ser feita via POST ou
HTTP Basic Authentication
Devise
@jlucasps
● 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
Devise
@jlucasps
● Omniauthable
○ Framework de autenticação compatível
com diversos providers (facebook, twitter,
openId, google, github), além dos
tradicionais username e password
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
Devise
@jlucasps
● Registerable
○ Permite cadastar usuários para utilizarem
uma aplicação
○ Editar as informações de cadastro do
usuário
○ Excluir o cadastro
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
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
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
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' }
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.
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:
....
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
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)
======================================
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
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
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
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
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
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
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
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
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)
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
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
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
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
Desenvolvimento
Web com Ruby on
Rails
João Lucas Pereira de Santana
gtalk | linkedin | twitter: jlucasps
Obrigado!

More Related Content

What's hot (20)

jQuery Mobile: Progressive Enhancement with HTML5
jQuery Mobile: Progressive Enhancement with HTML5
Todd Anderson
 
The Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.js
Holly Schinsky
 
Essential html tweaks for accessible themes
Essential html tweaks for accessible themes
Martin Stehle
 
What Web Developers Need to Know to Develop Windows 8 Apps
What Web Developers Need to Know to Develop Windows 8 Apps
Doris Chen
 
Introduction to jQuery Mobile
Introduction to jQuery Mobile
ejlp12
 
Vue.js for beginners
Vue.js for beginners
Julio Bitencourt
 
Ss 36932418[1]
Ss 36932418[1]
Ya Jinda
 
Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap
Rakesh Jha
 
jQuery Mobile with HTML5
jQuery Mobile with HTML5
madhurpgarg
 
You're Doing it Wrong - WordCamp Orlando
You're Doing it Wrong - WordCamp Orlando
Chris Scott
 
Test upload
Test upload
Darrell Lawson Jr.
 
ChocolateChip-UI
ChocolateChip-UI
GeorgeIshak
 
Introduction to jQuery Mobile - Web Deliver for All
Introduction to jQuery Mobile - Web Deliver for All
Marc Grabanski
 
Espacios en-tu-vida
Espacios en-tu-vida
epacheco1
 
Netvibes UWA workshop at ParisWeb 2007
Netvibes UWA workshop at ParisWeb 2007
Netvibes
 
Private slideshow
Private slideshow
sblackman
 
AtlasCamp 2013: Modernizing your Plugin UI
AtlasCamp 2013: Modernizing your Plugin UI
colleenfry
 
Articulo java web
Articulo java web
I.S.T. Santo Domingo
 
Templates81 special document
Templates81 special document
Lan Nguyen
 
Templates81 special document
Templates81 special document
Lan Nguyen
 
jQuery Mobile: Progressive Enhancement with HTML5
jQuery Mobile: Progressive Enhancement with HTML5
Todd Anderson
 
The Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.js
Holly Schinsky
 
Essential html tweaks for accessible themes
Essential html tweaks for accessible themes
Martin Stehle
 
What Web Developers Need to Know to Develop Windows 8 Apps
What Web Developers Need to Know to Develop Windows 8 Apps
Doris Chen
 
Introduction to jQuery Mobile
Introduction to jQuery Mobile
ejlp12
 
Ss 36932418[1]
Ss 36932418[1]
Ya Jinda
 
Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap
Rakesh Jha
 
jQuery Mobile with HTML5
jQuery Mobile with HTML5
madhurpgarg
 
You're Doing it Wrong - WordCamp Orlando
You're Doing it Wrong - WordCamp Orlando
Chris Scott
 
ChocolateChip-UI
ChocolateChip-UI
GeorgeIshak
 
Introduction to jQuery Mobile - Web Deliver for All
Introduction to jQuery Mobile - Web Deliver for All
Marc Grabanski
 
Espacios en-tu-vida
Espacios en-tu-vida
epacheco1
 
Netvibes UWA workshop at ParisWeb 2007
Netvibes UWA workshop at ParisWeb 2007
Netvibes
 
Private slideshow
Private slideshow
sblackman
 
AtlasCamp 2013: Modernizing your Plugin UI
AtlasCamp 2013: Modernizing your Plugin UI
colleenfry
 
Templates81 special document
Templates81 special document
Lan Nguyen
 
Templates81 special document
Templates81 special document
Lan Nguyen
 

Similar to Desenvolvimento web com Ruby on Rails (parte 6) (20)

Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on Rails
John Brunswick
 
Desenvolvimento web com Ruby on Rails (parte 4)
Desenvolvimento web com Ruby on Rails (parte 4)
Joao Lucas Santana
 
Devise and Rails
Devise and Rails
William Leeper
 
18.register login
18.register login
Razvan Raducanu, PhD
 
QuickConnect
QuickConnect
Annu G
 
Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)
Joao Lucas Santana
 
Agile Wordpress
Agile Wordpress
Filippo Dino
 
Mojolicious
Mojolicious
Marcos Rebelo
 
Php frameworks
Php frameworks
Anil Kumar Panigrahi
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
WebcampZG - Rails 4
WebcampZG - Rails 4
shnikola
 
Codegnitorppt
Codegnitorppt
sreedath c g
 
Exploring Symfony's Code
Exploring Symfony's Code
Wildan Maulana
 
PSD to WordPress
PSD to WordPress
Nile Flores
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Joao Lucas Santana
 
Nodejs.meetup
Nodejs.meetup
Vivian S. Zhang
 
User Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdf
Be Problem Solver
 
FamilySearch Reference Client
FamilySearch Reference Client
Dallan Quass
 
Flask – Python
Flask – Python
Max Claus Nunes
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi Appplication
olegmmiller
 
Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on Rails
John Brunswick
 
Desenvolvimento web com Ruby on Rails (parte 4)
Desenvolvimento web com Ruby on Rails (parte 4)
Joao Lucas Santana
 
QuickConnect
QuickConnect
Annu G
 
Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)
Joao Lucas Santana
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
WebcampZG - Rails 4
WebcampZG - Rails 4
shnikola
 
Exploring Symfony's Code
Exploring Symfony's Code
Wildan Maulana
 
PSD to WordPress
PSD to WordPress
Nile Flores
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Joao Lucas Santana
 
User Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdf
Be Problem Solver
 
FamilySearch Reference Client
FamilySearch Reference Client
Dallan Quass
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi Appplication
olegmmiller
 
Ad

Recently uploaded (20)

Edge-banding-machines-edgeteq-s-200-en-.pdf
Edge-banding-machines-edgeteq-s-200-en-.pdf
AmirStern2
 
Mastering AI Workflows with FME - Peak of Data & AI 2025
Mastering AI Workflows with FME - Peak of Data & AI 2025
Safe Software
 
PyData - Graph Theory for Multi-Agent Integration
PyData - Graph Theory for Multi-Agent Integration
barqawicloud
 
Murdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementary
JorgeSemperteguiMont
 
Oracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI Foundations
VICTOR MAESTRE RAMIREZ
 
Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...
BookNet Canada
 
Down the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training Roadblocks
Rustici Software
 
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Alliance
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
FME for Good: Integrating Multiple Data Sources with APIs to Support Local Ch...
FME for Good: Integrating Multiple Data Sources with APIs to Support Local Ch...
Safe Software
 
MuleSoft for AgentForce : Topic Center and API Catalog
MuleSoft for AgentForce : Topic Center and API Catalog
shyamraj55
 
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Anish Kumar
 
Your startup on AWS - How to architect and maintain a Lean and Mean account
Your startup on AWS - How to architect and maintain a Lean and Mean account
angelo60207
 
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
AmirStern2
 
AudGram Review: Build Visually Appealing, AI-Enhanced Audiograms to Engage Yo...
AudGram Review: Build Visually Appealing, AI-Enhanced Audiograms to Engage Yo...
SOFTTECHHUB
 
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
NTT DATA Technology & Innovation
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
Kubernetes Security Act Now Before It’s Too Late
Kubernetes Security Act Now Before It’s Too Late
Michael Furman
 
Enabling BIM / GIS integrations with Other Systems with FME
Enabling BIM / GIS integrations with Other Systems with FME
Safe Software
 
Oracle Cloud and AI Specialization Program
Oracle Cloud and AI Specialization Program
VICTOR MAESTRE RAMIREZ
 
Edge-banding-machines-edgeteq-s-200-en-.pdf
Edge-banding-machines-edgeteq-s-200-en-.pdf
AmirStern2
 
Mastering AI Workflows with FME - Peak of Data & AI 2025
Mastering AI Workflows with FME - Peak of Data & AI 2025
Safe Software
 
PyData - Graph Theory for Multi-Agent Integration
PyData - Graph Theory for Multi-Agent Integration
barqawicloud
 
Murdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementary
JorgeSemperteguiMont
 
Oracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI Foundations
VICTOR MAESTRE RAMIREZ
 
Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...
BookNet Canada
 
Down the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training Roadblocks
Rustici Software
 
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Alliance
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
FME for Good: Integrating Multiple Data Sources with APIs to Support Local Ch...
FME for Good: Integrating Multiple Data Sources with APIs to Support Local Ch...
Safe Software
 
MuleSoft for AgentForce : Topic Center and API Catalog
MuleSoft for AgentForce : Topic Center and API Catalog
shyamraj55
 
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Anish Kumar
 
Your startup on AWS - How to architect and maintain a Lean and Mean account
Your startup on AWS - How to architect and maintain a Lean and Mean account
angelo60207
 
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
AmirStern2
 
AudGram Review: Build Visually Appealing, AI-Enhanced Audiograms to Engage Yo...
AudGram Review: Build Visually Appealing, AI-Enhanced Audiograms to Engage Yo...
SOFTTECHHUB
 
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
NTT DATA Technology & Innovation
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
Kubernetes Security Act Now Before It’s Too Late
Kubernetes Security Act Now Before It’s Too Late
Michael Furman
 
Enabling BIM / GIS integrations with Other Systems with FME
Enabling BIM / GIS integrations with Other Systems with FME
Safe Software
 
Oracle Cloud and AI Specialization Program
Oracle Cloud and AI Specialization Program
VICTOR MAESTRE RAMIREZ
 
Ad

Desenvolvimento web com Ruby on Rails (parte 6)

  • 1. Desenvolvimento Web com Ruby on Rails João Lucas Pereira de Santana gtalk | linkedin | twitter: jlucasps
  • 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. ● 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. ● 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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) end end Criar factories
  • 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. 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. 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. Desenvolvimento Web com Ruby on Rails João Lucas Pereira de Santana gtalk | linkedin | twitter: jlucasps Obrigado!