rails_apps_composer: set up database

This commit is contained in:
Torsten Ruger 2016-03-21 18:46:06 +02:00
parent c4cd472f98
commit 729404e053
23 changed files with 423 additions and 11 deletions

View File

@ -312,8 +312,6 @@ GEM
thor (0.19.1)
thread_safe (0.3.5)
tilt (2.0.2)
turbolinks (2.5.3)
coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.7.2)
@ -377,7 +375,6 @@ DEPENDENCIES
spring
spring-commands-rspec
sqlite3
turbolinks
uglifier (>= 1.3.0)
web-console (~> 2.0)

View File

@ -8,6 +8,6 @@ class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end

View File

@ -0,0 +1,10 @@
class CreateAdminService
def call
user = User.find_or_create_by!(email: Rails.application.secrets.admin_email) do |user|
user.password = Rails.application.secrets.admin_password
user.password_confirmation = Rails.application.secrets.admin_password
user.confirm!
user.admin!
end
end
end

View File

@ -30,7 +30,7 @@ Rails.application.configure do
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = { :host => Rails.application.secrets.domain_name }
# Randomize the order test cases are executed.
config.active_support.test_order = :random

View File

@ -12,7 +12,7 @@ Devise.setup do |config|
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
config.mailer_sender = 'no-reply@' + Rails.application.secrets.domain_name
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'

View File

@ -11,12 +11,21 @@
# if you're sharing your code publicly.
development:
admin_name: First User
admin_email: user@example.com
admin_password: changeme
domain_name: example.com
secret_key_base: 6fbc7972b587359c086a6c6738dca91a5cd53f635bdfba31c7b23721a27e1d89bf8c490dfc3ebe773bcdb98d2add0946ea924321bad66499b893d88fc827b883
test:
domain_name: example.com
secret_key_base: a0a18747d0172bfadf4187e6c01be490f452539aeaa4d74bada88ef851d7a2dfabcde91552d3689e9eb71caf9062e5d8b28fbeb55c6f429d92d462655c25d60c
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
admin_name: <%= ENV["ADMIN_NAME"] %>
admin_email: <%= ENV["ADMIN_EMAIL"] %>
admin_password: <%= ENV["ADMIN_PASSWORD"] %>
domain_name: <%= ENV["DOMAIN_NAME"] %>
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

View File

@ -0,0 +1,23 @@
class DeviseInvitableAddToUsers < ActiveRecord::Migration
def up
change_table :users do |t|
t.string :invitation_token
t.datetime :invitation_created_at
t.datetime :invitation_sent_at
t.datetime :invitation_accepted_at
t.integer :invitation_limit
t.references :invited_by, polymorphic: true
t.integer :invitations_count, default: 0
t.index :invitations_count
t.index :invitation_token, unique: true # for invitable
t.index :invited_by_id
end
end
def down
change_table :users do |t|
t.remove_references :invited_by, polymorphic: true
t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
end
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160321164456) do
ActiveRecord::Schema.define(version: 20160321164557) do
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
@ -31,9 +31,21 @@ ActiveRecord::Schema.define(version: 20160321164456) do
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.integer "role"
t.string "invitation_token"
t.datetime "invitation_created_at"
t.datetime "invitation_sent_at"
t.datetime "invitation_accepted_at"
t.integer "invitation_limit"
t.integer "invited_by_id"
t.string "invited_by_type"
t.integer "invitations_count", default: 0
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true
add_index "users", ["invitations_count"], name: "index_users_on_invitations_count"
add_index "users", ["invited_by_id"], name: "index_users_on_invited_by_id"
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

View File

@ -5,3 +5,5 @@
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
user = CreateAdminService.new.call
puts 'CREATED ADMIN USER: ' << user.email

View File

@ -1,5 +1,13 @@
FactoryGirl.define do
factory :user do
confirmed_at Time.now
name "Test User"
email "test@example.com"
password "please123"
trait :admin do
role 'admin'
end
end
end

View File

@ -0,0 +1,49 @@
# Feature: Sign in
# As a user
# I want to sign in
# So I can visit protected areas of the site
feature 'Sign in', :devise do
# Scenario: User cannot sign in if not registered
# Given I do not exist as a user
# When I sign in with valid credentials
# Then I see an invalid credentials message
scenario 'user cannot sign in if not registered' do
signin('test@example.com', 'please123')
expect(page).to have_content I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email'
end
# Scenario: User can sign in with valid credentials
# Given I exist as a user
# And I am not signed in
# When I sign in with valid credentials
# Then I see a success message
scenario 'user can sign in with valid credentials' do
user = FactoryGirl.create(:user)
signin(user.email, user.password)
expect(page).to have_content I18n.t 'devise.sessions.signed_in'
end
# Scenario: User cannot sign in with wrong email
# Given I exist as a user
# And I am not signed in
# When I sign in with a wrong email
# Then I see an invalid email message
scenario 'user cannot sign in with wrong email' do
user = FactoryGirl.create(:user)
signin('invalid@email.com', user.password)
expect(page).to have_content I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email'
end
# Scenario: User cannot sign in with wrong password
# Given I exist as a user
# And I am not signed in
# When I sign in with a wrong password
# Then I see an invalid password message
scenario 'user cannot sign in with wrong password' do
user = FactoryGirl.create(:user)
signin(user.email, 'invalidpass')
expect(page).to have_content I18n.t 'devise.failure.invalid', authentication_keys: 'email'
end
end

View File

@ -0,0 +1,21 @@
# Feature: Sign out
# As a user
# I want to sign out
# So I can protect my account from unauthorized access
feature 'Sign out', :devise do
# Scenario: User signs out successfully
# Given I am signed in
# When I sign out
# Then I see a signed out message
scenario 'user signs out successfully' do
user = FactoryGirl.create(:user)
signin(user.email, user.password)
expect(page).to have_content I18n.t 'devise.sessions.signed_in'
click_link 'Sign out'
expect(page).to have_content I18n.t 'devise.sessions.signed_out'
end
end

View File

@ -0,0 +1,32 @@
include Warden::Test::Helpers
Warden.test_mode!
# Feature: User delete
# As a user
# I want to delete my user profile
# So I can close my account
feature 'User delete', :devise, :js do
after(:each) do
Warden.test_reset!
end
# Scenario: User can delete own account
# Given I am signed in
# When I delete my account
# Then I should see an account deleted message
scenario 'user can delete own account' do
skip 'skip a slow test'
user = FactoryGirl.create(:user)
login_as(user, :scope => :user)
visit edit_user_registration_path(user)
click_button 'Cancel my account'
page.driver.browser.switch_to.alert.accept
expect(page).to have_content I18n.t 'devise.registrations.destroyed'
end
end

View File

@ -0,0 +1,42 @@
include Warden::Test::Helpers
Warden.test_mode!
# Feature: User edit
# As a user
# I want to edit my user profile
# So I can change my email address
feature 'User edit', :devise do
after(:each) do
Warden.test_reset!
end
# Scenario: User changes email address
# Given I am signed in
# When I change my email address
# Then I see an account updated message
scenario 'user changes email address' do
user = FactoryGirl.create(:user)
login_as(user, :scope => :user)
visit edit_user_registration_path(user)
fill_in 'Email', :with => 'newemail@example.com'
fill_in 'Current password', :with => user.password
click_button 'Update'
txts = [I18n.t( 'devise.registrations.updated'), I18n.t( 'devise.registrations.update_needs_confirmation')]
expect(page).to have_content(/.*#{txts[0]}.*|.*#{txts[1]}.*/)
end
# Scenario: User cannot edit another user's profile
# Given I am signed in
# When I try to edit another user's profile
# Then I see my own 'edit profile' page
scenario "user cannot cannot edit another user's profile", :me do
me = FactoryGirl.create(:user)
other = FactoryGirl.create(:user, email: 'other@example.com')
login_as(me, :scope => :user)
visit edit_user_registration_path(other)
expect(page).to have_content 'Edit User'
expect(page).to have_field('Email', with: me.email)
end
end

View File

@ -0,0 +1,25 @@
include Warden::Test::Helpers
Warden.test_mode!
# Feature: User index page
# As a user
# I want to see a list of users
# So I can see who has registered
feature 'User index page', :devise do
after(:each) do
Warden.test_reset!
end
# Scenario: User listed on index page
# Given I am signed in
# When I visit the user index page
# Then I see my own email address
scenario 'user sees own email address' do
user = FactoryGirl.create(:user, :admin)
login_as(user, scope: :user)
visit users_path
expect(page).to have_content user.email
end
end

View File

@ -0,0 +1,39 @@
include Warden::Test::Helpers
Warden.test_mode!
# Feature: User profile page
# As a user
# I want to visit my user profile page
# So I can see my personal account data
feature 'User profile page', :devise do
after(:each) do
Warden.test_reset!
end
# Scenario: User sees own profile
# Given I am signed in
# When I visit the user profile page
# Then I see my own email address
scenario 'user sees own profile' do
user = FactoryGirl.create(:user)
login_as(user, :scope => :user)
visit user_path(user)
expect(page).to have_content 'User'
expect(page).to have_content user.email
end
# Scenario: User cannot see another user's profile
# Given I am signed in
# When I visit another user's profile
# Then I see an 'access denied' message
scenario "user cannot see another user's profile" do
me = FactoryGirl.create(:user)
other = FactoryGirl.create(:user, email: 'other@example.com')
login_as(me, :scope => :user)
Capybara.current_session.driver.header 'Referer', root_path
visit user_path(other)
expect(page).to have_content 'Access denied.'
end
end

View File

@ -0,0 +1,62 @@
# Feature: Sign up
# As a visitor
# I want to sign up
# So I can visit protected areas of the site
feature 'Sign Up', :devise do
# Scenario: Visitor can sign up with valid email address and password
# Given I am not signed in
# When I sign up with a valid email address and password
# Then I see a successful sign up message
scenario 'visitor can sign up with valid email address and password' do
sign_up_with('test@example.com', 'please123', 'please123')
txts = [I18n.t( 'devise.registrations.signed_up'), I18n.t( 'devise.registrations.signed_up_but_unconfirmed')]
expect(page).to have_content(/.*#{txts[0]}.*|.*#{txts[1]}.*/)
end
# Scenario: Visitor cannot sign up with invalid email address
# Given I am not signed in
# When I sign up with an invalid email address
# Then I see an invalid email message
scenario 'visitor cannot sign up with invalid email address' do
sign_up_with('bogus', 'please123', 'please123')
expect(page).to have_content 'Email is invalid'
end
# Scenario: Visitor cannot sign up without password
# Given I am not signed in
# When I sign up without a password
# Then I see a missing password message
scenario 'visitor cannot sign up without password' do
sign_up_with('test@example.com', '', '')
expect(page).to have_content "Password can't be blank"
end
# Scenario: Visitor cannot sign up with a short password
# Given I am not signed in
# When I sign up with a short password
# Then I see a 'too short password' message
scenario 'visitor cannot sign up with a short password' do
sign_up_with('test@example.com', 'please', 'please')
expect(page).to have_content "Password is too short"
end
# Scenario: Visitor cannot sign up without password confirmation
# Given I am not signed in
# When I sign up without a password confirmation
# Then I see a missing password confirmation message
scenario 'visitor cannot sign up without password confirmation' do
sign_up_with('test@example.com', 'please123', '')
expect(page).to have_content "Password confirmation doesn't match"
end
# Scenario: Visitor cannot sign up with mismatched password and confirmation
# Given I am not signed in
# When I sign up with a mismatched password confirmation
# Then I should see a mismatched password message
scenario 'visitor cannot sign up with mismatched password and confirmation' do
sign_up_with('test@example.com', 'please123', 'mismatch')
expect(page).to have_content "Password confirmation doesn't match"
end
end

View File

@ -1,5 +1,13 @@
require 'rails_helper'
describe User do
before(:each) { @user = User.new(email: 'user@example.com') }
subject { @user }
it { should respond_to(:email) }
it "#email returns a string" do
expect(@user.email).to match 'user@example.com'
end
RSpec.describe User, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,47 @@
describe UserPolicy do
subject { UserPolicy }
let (:current_user) { FactoryGirl.build_stubbed :user }
let (:other_user) { FactoryGirl.build_stubbed :user }
let (:admin) { FactoryGirl.build_stubbed :user, :admin }
permissions :index? do
it "denies access if not an admin" do
expect(UserPolicy).not_to permit(current_user)
end
it "allows access for an admin" do
expect(UserPolicy).to permit(admin)
end
end
permissions :show? do
it "prevents other users from seeing your profile" do
expect(subject).not_to permit(current_user, other_user)
end
it "allows you to see your own profile" do
expect(subject).to permit(current_user, current_user)
end
it "allows an admin to see any profile" do
expect(subject).to permit(admin)
end
end
permissions :update? do
it "prevents updates if not an admin" do
expect(subject).not_to permit(current_user)
end
it "allows an admin to make updates" do
expect(subject).to permit(admin)
end
end
permissions :destroy? do
it "prevents deleting yourself" do
expect(subject).not_to permit(current_user, current_user)
end
it "allows an admin to delete any user" do
expect(subject).to permit(admin, other_user)
end
end
end

3
spec/support/devise.rb Normal file
View File

@ -0,0 +1,3 @@
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end

4
spec/support/helpers.rb Normal file
View File

@ -0,0 +1,4 @@
require 'support/helpers/session_helpers'
RSpec.configure do |config|
config.include Features::SessionHelpers, type: :feature
end

View File

@ -0,0 +1,18 @@
module Features
module SessionHelpers
def sign_up_with(email, password, confirmation)
visit new_user_registration_path
fill_in 'Email', with: email
fill_in 'Password', with: password
fill_in 'Password confirmation', :with => confirmation
click_button 'Sign up'
end
def signin(email, password)
visit new_user_session_path
fill_in 'Email', with: email
fill_in 'Password', with: password
click_button 'Sign in'
end
end
end

1
spec/support/pundit.rb Normal file
View File

@ -0,0 +1 @@
require 'pundit/rspec'