rails_apps_composer: set up database
This commit is contained in:
parent
c4cd472f98
commit
729404e053
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"] %>
|
||||
|
|
|
@ -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
|
14
db/schema.rb
14
db/schema.rb
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
RSpec.configure do |config|
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
require 'support/helpers/session_helpers'
|
||||
RSpec.configure do |config|
|
||||
config.include Features::SessionHelpers, type: :feature
|
||||
end
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
require 'pundit/rspec'
|
Loading…
Reference in New Issue