Skip to content

Commit

Permalink
Fixes Issue #68 (#69)
Browse files Browse the repository at this point in the history
* Fixes #68 via user.skip_reconfirmation!
Updates registrations_controller and confirmations_controller to match devise API, Adds devise-inivitable to test application; adds sign-up form to test application

* Adds instructions for manually running test application

* Updates bundle

* Adds links to README
  • Loading branch information
jekuno authored Feb 20, 2017
1 parent 063981c commit d081983
Show file tree
Hide file tree
Showing 20 changed files with 244 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ GEM
erubis (2.7.0)
globalid (0.3.7)
activesupport (>= 4.1.0)
i18n (0.7.0)
i18n (0.8.0)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Open http://127.0.0.1:3000/users/sign_up in your browser.
You're ready to go!

### Previous sample app
For your reference: An outdated milia+devise sample app can be found at https://github.com/dsaronin/sample-milia-app
For your reference: An outdated milia+devise sample app can be found at [https://github.com/dsaronin/sample-milia-app](https://github.com/dsaronin/sample-milia-app)
and is live on Heroku: http://sample-milia.herokuapp.com
The according instructions on how to generate this sample app can be found at [doc/sample.sh](doc/sample.sh).

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/confirmations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def update

if resource.errors.empty?
log_action( "invitee confirmed" )
set_flash_message(:notice, :confirmed) if is_flashing_format?
set_flash_message(:notice, :confirmed)
# sign in automatically
sign_in_tenanted_and_redirect(resource)

Expand Down
23 changes: 13 additions & 10 deletions app/controllers/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,30 +104,33 @@ def sign_out_session!()
# same as in devise gem EXCEPT need to prep signup form variables
# ------------------------------------------------------------------------------
def devise_create( user_params )

build_resource(user_params)

# if we're using milia's invite_member helpers
# if we're using milia's invite_member helpers
if ::Milia.use_invite_member
# then flag for our confirmable that we won't need to set up a password
# then flag for our confirmable that we won't need to set up a password
resource.skip_confirm_change_password = true
end

if resource.save
yield resource if block_given?
log_action( "devise: signup user success", resource )
resource.save
yield resource if block_given?
log_action( "devise: signup user success", resource )

if resource.persisted?
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
set_flash_message! :notice, :signed_up
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
expire_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
# re-show signup view
clean_up_passwords resource
log_action( "devise: signup user failure", resource )
set_minimum_password_length
prep_signup_view( @tenant, resource, params[:coupon] )
respond_with resource
end
Expand Down
1 change: 1 addition & 0 deletions lib/milia/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def acts_as_universal_and_determines_account()
after_create do |new_user|
tenant = Tenant.find(Thread.current[:tenant_id])
unless tenant.users.include?(new_user)
new_user.skip_reconfirmation! # For details why this is needed see milia issue #68
tenant.users << new_user # add user to this tenant if not already there
end
end # before_create do
Expand Down
26 changes: 13 additions & 13 deletions lib/milia/invite_member.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ module Milia
module InviteMember

# #############################################################################

def self.included(base)
base.extend ClassMethods
end

# #############################################################################
# #############################################################################
module ClassMethods

end # module ClassMethods
# #############################################################################
# #############################################################################

# ------------------------------------------------------------------------
# new function to set the password without knowing the current password
# new function to set the password without knowing the current password
# ------------------------------------------------------------------------
def attempt_set_password(params)
p = {}
Expand All @@ -32,7 +32,7 @@ def attempt_set_password(params)
def has_no_password?
self.encrypted_password.blank?
end

# ------------------------------------------------------------------------
# new function to provide access to protected method unless_confirmed
# ------------------------------------------------------------------------
Expand All @@ -43,35 +43,35 @@ def only_if_unconfirmed
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------

# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# save_and_invite_member -- saves the new user record thus inviting member
# via devise
# if password missing; gens a password
# ensures email exists and that email is unique and not already in system
# ------------------------------------------------------------------------
def save_and_invite_member( )
# ------------------------------------------------------------------------
def save_and_invite_member
status = nil

if (self.email.blank?)
self.errors.add(:email, :blank)
elsif User.where([ "lower(email) = ?", self.email.downcase ]).present?
self.errors.add(:email, :taken)
else
check_or_set_password()
else
check_or_set_password()
status = self.save && self.errors.empty?
end

return status
end

# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# check_or_set_password -- if password missing, generates a password
# ASSUMES: Milia.use_invite_member
# ------------------------------------------------------------------------
def check_or_set_password( )
# ------------------------------------------------------------------------
def check_or_set_password

if self.password.blank?
self.password =
self.password =
::Milia::Password.generate(
8, Password::ONE_DIGIT | Password::ONE_CASE
)
Expand Down
10 changes: 6 additions & 4 deletions test/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ end
gem "rack-timeout"
gem 'rails_12factor'

gem 'devise' # , '~>3.2'
gem 'devise' #, :path => "./devise-4.2.0"
gem 'devise_invitable', "~> 1.7"

# airbrake is optional and configured by config.use_airbrake in milia initializer
# default is false; if you change it to true, uncomment out the line below
Expand All @@ -76,9 +77,10 @@ gem "recaptcha", require: "recaptcha/rails"
gem "activerecord-session_store", github: "rails/activerecord-session_store"

group :test do
gem "shoulda" # , "3.5.0"
gem "shoulda-matchers" # , "~>2.1.0"
gem "shoulda-context" # , "~>1.1.2"
gem "shoulda"
gem "shoulda-matchers"
gem "shoulda-context"
end

# Test the current milia version (which is part of this repo)
gem 'milia', :path => "../../milia"
4 changes: 4 additions & 0 deletions test/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ GEM
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
devise_invitable (1.7.0)
actionmailer (>= 4.0.0)
devise (>= 4.0.0)
erubis (2.7.0)
execjs (2.7.0)
globalid (0.3.7)
Expand Down Expand Up @@ -213,6 +216,7 @@ DEPENDENCIES
activerecord-session_store!
coffee-rails
devise
devise_invitable (~> 1.7)
haml-rails
html2haml
jbuilder
Expand Down
15 changes: 15 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ Milia is tested using `minitest`.
Tests run in context of a multi-tenanted example application
(which resides in the `milia/test` directory).

## Exploring test application manually
Tests run in context of a multi-tenanted example application.
To execute it manually do:

```
cd test
bundle install
RAILS_ENV=test rake db:setup
RAILS_ENV=test rails server
```

* Open [http://127.0.0.1:3000/users/sign_up](http://127.0.0.1:3000/users/sign_up) in your browser
in order to add a new tenant.
* Open [http://127.0.0.1:3000/users/invitation/new](http://127.0.0.1:3000/users/invitation/new) to invite new users.

## Running tests

The `test_helper.rb` takes care of maintaining the database
Expand Down
4 changes: 2 additions & 2 deletions test/app/models/member.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Member < ActiveRecord::Base
has_many :teams, :through => :team_assets, :source => 'team'
has_many :posts
has_many :zines, :through => :posts, :source => 'zine'


DEFAULT_ADMIN = {
first_name: "Admin",
Expand All @@ -25,7 +25,7 @@ def self.create_org_admin(user)
end

return new_member

end


Expand Down
8 changes: 4 additions & 4 deletions test/app/models/tenant.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class Tenant < ActiveRecord::Base
acts_as_universal_and_determines_tenant

has_many :members, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :zines, dependent: :destroy
has_many :teams, dependent: :destroy
has_many :members, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :zines, dependent: :destroy
has_many :teams, dependent: :destroy
has_many :team_assets, dependent: :destroy

# ------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions test/app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
class User < ActiveRecord::Base
acts_as_universal_and_determines_account

# Include default devise modules. Others available are:
# :lockable, :encryptable, and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable

has_one :member, :dependent => :destroy
Expand Down
50 changes: 50 additions & 0 deletions test/app/views/devise/registrations/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
%div.authform
%h1 Simple Milia App
.block#block-signup
%h2 New Organizational Sign up
.content
%span.description
%i
If you're a member of an existing group in our system,
click the activate link in the invitation email from your organization's admin.
You should not sign up for a new organizational account.
%br
.flash
- flash.each do |type, message|
%div{ :class => "message #{type}" }
%p= message
- flash.clear # clear contents so we won't see it again

= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "form" }) do |f|
= devise_error_messages!
.group
= f.label :email, :class => "label"
= f.text_field :email, :class => "text_field"
%span.description Ex. [email protected]
.group
= f.label :password, :class => "label"
= f.password_field :password, :class => "text_field"
%span.description must be at least 8 characters
.group
= f.label :password_confirmation, "Re-enter Password", :class => "label"
= f.password_field :password_confirmation, :class => "text_field"
%span.description to confirm your password

.group
= fields_for( :tenant ) do |w|
= w.label( :name, 'Organization', :class => "label" )
= w.text_field( :name, :class => "text_field")
%span.description unique name for your group or organization for the new account

- if ::Milia.use_coupon
- @coupon ||= {}
.group
= label_tag( 'coupon', 'Coupon code', :class => "label" )
= text_field_tag( "coupon[coupon]", @coupon['coupon'].to_s, :size => 8, :class => "text_field" )
%span.description optional promotional code, if any

.group.navform.wat-cf
%button.button{ :type => "submit" }
Sign up
= render :partial => "devise/shared/links"

4 changes: 4 additions & 0 deletions test/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment', __FILE__)
run Rails.application
48 changes: 48 additions & 0 deletions test/config/initializers/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,54 @@
# Setup a pepper to generate the encrypted password.
config.pepper = 'b6b4d6bdcf41f0cc02d9c2b55746ac7fc724f5d22d180431bdda6a58e7dfa3d3417de488e4c58a9bdff0f5b609bec2b8a1b8866fc66cf09a5d6337adc14f2021'

# ==> Configuration for :invitable
# The period the generated invitation token is valid, after
# this period, the invited resource won't be able to accept the invitation.
# When invite_for is 0 (the default), the invitation won't expire.
# config.invite_for = 2.weeks

# Number of invitations users can send.
# - If invitation_limit is nil, there is no limit for invitations, users can
# send unlimited invitations, invitation_limit column is not used.
# - If invitation_limit is 0, users can't send invitations by default.
# - If invitation_limit n > 0, users can send n invitations.
# You can change invitation_limit column for some users so they can send more
# or less invitations, even with global invitation_limit = 0
# Default: nil
# config.invitation_limit = 5

# The key to be used to check existing users when sending an invitation
# and the regexp used to test it when validate_on_invite is not set.
# config.invite_key = {:email => /\A[^@]+@[^@]+\z/}
# config.invite_key = {:email => /\A[^@]+@[^@]+\z/, :username => nil}

# Flag that force a record to be valid before being actually invited
# Default: false
# config.validate_on_invite = true

# Resend invitation if user with invited status is invited again
# Default: true
# config.resend_invitation = false

# The class name of the inviting model. If this is nil,
# the #invited_by association is declared to be polymorphic.
# Default: nil
# config.invited_by_class_name = 'User'

# The foreign key to the inviting model (if invited_by_class_name is set)
# Default: :invited_by_id
# config.invited_by_foreign_key = :invited_by_id

# The column name used for counter_cache column. If this is nil,
# the #invited_by association is declared without counter_cache.
# Default: nil
# config.invited_by_counter_cache = :invitations_count

# Auto-login after the user accepts the invite. If this is false,
# the user will need to manually log in after accepting the invite.
# Default: true
# config.allow_insecure_sign_in_after_accept = false

# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming his account. For instance, if set to 2.days, the user will be
Expand Down
Loading

0 comments on commit d081983

Please sign in to comment.