jobshop 0.0.41 → 0.0.53
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/email_token_validation.rb +59 -0
- data/app/controllers/concerns/registration_token_validation.rb +34 -18
- data/app/controllers/jobshop/application_controller.rb +1 -54
- data/app/controllers/jobshop/sessions_controller.rb +6 -0
- data/app/controllers/jobshop/teams/lookups_controller.rb +1 -2
- data/app/controllers/jobshop/teams/registrations_controller.rb +2 -2
- data/app/mailers/jobshop/teams_mailer.rb +3 -3
- data/app/models/jobshop/user.rb +5 -1
- data/app/views/devise/sessions/new.html.haml +1 -0
- data/app/views/jobshop/dashboards/show.html.haml +1 -1
- data/app/views/jobshop/teams/lookups/show.html.haml +1 -0
- data/app/views/jobshop/teams_mailer/found_teams.html.haml +11 -0
- data/app/views/jobshop/teams_mailer/found_teams.text.erb +2 -1
- data/app/views/layouts/jobshop/unauthenticated.html.haml +1 -1
- data/config/initializers/devise.rb +1 -1
- data/config/routes.rb +9 -1
- data/lib/jobshop/templates/secrets.yml.erb +7 -2
- data/lib/jobshop/version.rb +1 -1
- data/lib/jobshop.rb +6 -2
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a2d1798548ecae570f0b45babfa2e513b82395c
|
4
|
+
data.tar.gz: bc7448f4acea0f1582843a1a47ff9b98a1c4aae6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 649182157861589f953e47725d6947e86f3245e81e2c90c8d1b36127865fdacd74a4498303dd6bd99b9f837752353dfcd211733ad43c9963d88a5d83346bf3ae
|
7
|
+
data.tar.gz: e7b646ec641cceae9c9e699a5f4afb9e5d725fcd1f0a066e7974af05cf1127ba4af99e484b1966dee8b71972aba0a4faf24d20a489a0f5e26484ee6dd46eca39
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class EmailTokenValidation
|
2
|
+
def self.before(controller)
|
3
|
+
@token = EmailToken.new(
|
4
|
+
controller.params.fetch(:user_email, nil),
|
5
|
+
controller.params.fetch(:email_authentication_token, nil)
|
6
|
+
)
|
7
|
+
|
8
|
+
if @token.valid?
|
9
|
+
sign_out_current_scope
|
10
|
+
sign_in token.user
|
11
|
+
token.destroy
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class EmailToken
|
16
|
+
attr_reader :token
|
17
|
+
|
18
|
+
def initialize(email, token)
|
19
|
+
@email, @token = email, token
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
present? && user && token && !expired? && secure_compare
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def present?
|
28
|
+
@email.present? && @token.present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def user
|
32
|
+
@user ||= Jobshop::User.where(email: @email)
|
33
|
+
.where.not(email_authentication_token_sent_at: nil).first
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
user.update({
|
38
|
+
email_authentication_token: nil,
|
39
|
+
email_authentication_token_sent_at: nil
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
def secure_compare
|
44
|
+
# Notice how we use Devise.secure_compare to compare the token in the
|
45
|
+
# database with the token given in the params, mitigating timing
|
46
|
+
# attacks.
|
47
|
+
Devise.secure_compare(user.email_authentication_token, token)
|
48
|
+
end
|
49
|
+
|
50
|
+
def expired?
|
51
|
+
@expired ||= Time.now >= expires_on
|
52
|
+
end
|
53
|
+
|
54
|
+
def expires_on
|
55
|
+
# TODO: Make token expiration configurable in initializers/jobshop.rb.
|
56
|
+
@expires_on ||= user.email_authentication_token_sent_at + 6.hours
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,25 +1,41 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
class RegistrationTokenValidation
|
2
|
+
def self.before(controller)
|
3
|
+
new(controller.dup)
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller.dup
|
8
|
+
@token = @controller.params.fetch(:registration_token, nil)
|
9
|
+
@team_id = @controller.params.fetch(:team_id, nil)
|
8
10
|
|
9
|
-
|
10
|
-
@
|
11
|
+
if @token
|
12
|
+
@controller.redirect_to(@controller.new_user_session_path) unless valid?
|
11
13
|
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
!expired? && !owned? && resolves?
|
18
|
+
end
|
12
19
|
|
13
|
-
|
14
|
-
|
15
|
-
|
20
|
+
private
|
21
|
+
def team
|
22
|
+
@team ||= Jobshop::Team.where(id: @team_id).first
|
23
|
+
end
|
16
24
|
|
17
|
-
|
18
|
-
|
25
|
+
def resolves?
|
26
|
+
encrypted_token = Devise.token_generator.digest(
|
27
|
+
Jobshop::Team, :registration_token, @token)
|
19
28
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
# Notice how we use Devise.secure_compare to compare the token in the
|
30
|
+
# database with the token given in the params, mitigating timing attacks.
|
31
|
+
Devise.secure_compare(team.registration_token, encrypted_token)
|
32
|
+
end
|
33
|
+
|
34
|
+
def expired?
|
35
|
+
@expired ||= !team.registration_token_period_valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
def owned?
|
39
|
+
@owned ||= team.owner.present?
|
24
40
|
end
|
25
41
|
end
|
@@ -10,7 +10,7 @@ module Jobshop
|
|
10
10
|
|
11
11
|
protect_from_forgery
|
12
12
|
|
13
|
-
before_action
|
13
|
+
before_action EmailTokenValidation
|
14
14
|
before_action :authenticate_user!
|
15
15
|
|
16
16
|
# after_action :verify_authorized, except: :index
|
@@ -18,67 +18,14 @@ module Jobshop
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
def authenticate_user_from_email!
|
22
|
-
token = EmailAuthenticationToken.new(
|
23
|
-
params.fetch(:user_email, nil),
|
24
|
-
params.fetch(:email_authentication_token, nil)
|
25
|
-
)
|
26
|
-
|
27
|
-
if token.valid?
|
28
|
-
sign_in token.user
|
29
|
-
token.destroy
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
21
|
def layout_for_application
|
34
22
|
if devise_controller? && controller_name == "sessions" ||
|
35
23
|
controller_path == "jobshop/teams/lookups"
|
36
24
|
"jobshop/unauthenticated"
|
37
25
|
else
|
38
|
-
|
39
26
|
"jobshop/application"
|
40
27
|
end
|
41
28
|
end
|
42
29
|
|
43
|
-
class EmailAuthenticationToken
|
44
|
-
attr_reader :token
|
45
|
-
|
46
|
-
def initialize(email, token)
|
47
|
-
@email = email
|
48
|
-
@token = token
|
49
|
-
end
|
50
|
-
|
51
|
-
def valid?
|
52
|
-
user && token && !expired? && secure_compare
|
53
|
-
end
|
54
|
-
|
55
|
-
def user
|
56
|
-
@user ||= Jobshop::User.where(email: @email)
|
57
|
-
.where.not(email_authentication_token_sent_at: nil).first
|
58
|
-
end
|
59
|
-
|
60
|
-
def destroy
|
61
|
-
user.update({
|
62
|
-
email_authentication_token: nil,
|
63
|
-
email_authentication_token_sent_at: nil
|
64
|
-
})
|
65
|
-
end
|
66
|
-
|
67
|
-
def secure_compare
|
68
|
-
# Notice how we use Devise.secure_compare to compare the token in the
|
69
|
-
# database with the token given in the params, mitigating timing
|
70
|
-
# attacks.
|
71
|
-
Devise.secure_compare(user.email_authentication_token, token)
|
72
|
-
end
|
73
|
-
|
74
|
-
def expired?
|
75
|
-
@expired ||= Time.now >= expires_on
|
76
|
-
end
|
77
|
-
|
78
|
-
def expires_on
|
79
|
-
# TODO: Make token expiration configurable in initializers/jobshop.rb.
|
80
|
-
@expires_on ||= user.email_authentication_token_sent_at + 6.hours
|
81
|
-
end
|
82
|
-
end
|
83
30
|
end
|
84
31
|
end
|
@@ -10,12 +10,11 @@ module Jobshop
|
|
10
10
|
|
11
11
|
def create
|
12
12
|
emails = params[:user][:email].split(",").map(&:strip).take(5)
|
13
|
-
|
14
13
|
Jobshop::Team.grouped_by_email(emails).each_pair do |email, teams|
|
15
14
|
Jobshop::TeamsMailer.found_teams(email, teams).deliver_later
|
16
15
|
end
|
17
16
|
|
18
|
-
redirect_to
|
17
|
+
redirect_to teams_lookup_path
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
@@ -2,10 +2,10 @@ require_dependency "jobshop/application_controller"
|
|
2
2
|
|
3
3
|
module Jobshop
|
4
4
|
class Teams::RegistrationsController < ApplicationController
|
5
|
-
before_action RegistrationTokenValidation
|
6
|
-
|
7
5
|
skip_before_action :authenticate_user!
|
8
6
|
|
7
|
+
before_action RegistrationTokenValidation
|
8
|
+
|
9
9
|
layout "jobshop/unauthenticated"
|
10
10
|
|
11
11
|
def new
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Jobshop
|
2
2
|
class TeamsMailer < ApplicationMailer
|
3
|
-
def found_teams(
|
4
|
-
@user =
|
3
|
+
def found_teams(email, teams)
|
4
|
+
@user = Jobshop::User.where(email: email).first
|
5
5
|
@teams = teams
|
6
6
|
|
7
|
-
mail(to:
|
7
|
+
mail(to: email, subject: "We found your Jobshop Teams!")
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
data/app/models/jobshop/user.rb
CHANGED
@@ -16,8 +16,12 @@ module Jobshop
|
|
16
16
|
presence: { if: :password_required? },
|
17
17
|
confirmation: { if: :password_required? }
|
18
18
|
|
19
|
-
|
19
|
+
def self.find_for_authentication(warden_conditions)
|
20
|
+
where(email: warden_conditions[:email],
|
21
|
+
team_id: warden_conditions[:team_id]).first
|
22
|
+
end
|
20
23
|
|
24
|
+
private
|
21
25
|
def generate_email_authentication_token
|
22
26
|
loop do
|
23
27
|
token = Devise.friendly_token
|
@@ -27,7 +27,7 @@
|
|
27
27
|
%span(class="visuallyhidden") User Actions
|
28
28
|
%ul(class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="accbtn")
|
29
29
|
%li(class="mdl-menu__item")
|
30
|
-
%a(href="#{destroy_user_session_path}" data-method="delete") Sign out
|
30
|
+
%a(href="#{destroy_user_session_path(team_id: current_user.team_id)}" data-method="delete") Sign out
|
31
31
|
%nav(class="demo-navigation mdl-navigation mdl-color--blue-grey-800")
|
32
32
|
%a(class="mdl-navigation__link" href="")
|
33
33
|
%i(class="mdl-color-text--blue-grey-400 material-icons" role="presentation") home
|
@@ -8,7 +8,7 @@
|
|
8
8
|
%nav.mdl-navigation
|
9
9
|
%a.mdl-navigation__link{ href: jobshop.about_path }
|
10
10
|
About
|
11
|
-
%a.mdl-navigation__link.mdl-color-text--pink{ href: jobshop.
|
11
|
+
%a.mdl-navigation__link.mdl-color-text--pink{ href: jobshop.teams_lookup_path }
|
12
12
|
Sign In
|
13
13
|
|
14
14
|
= yield
|
@@ -36,7 +36,7 @@ Devise.setup do |config|
|
|
36
36
|
# filter. You can also supply a hash where the value is a boolean determining
|
37
37
|
# whether or not authentication should be aborted when the value is not
|
38
38
|
# present.
|
39
|
-
|
39
|
+
config.authentication_keys = [ :email, :team_id ]
|
40
40
|
|
41
41
|
# Configure parameters from the request object used for authentication. Each
|
42
42
|
# entry given should be a request method and it will automatically be passed
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
Jobshop::Engine.routes.draw do
|
2
|
-
|
2
|
+
default_url_options(Jobshop.configuration.default_url_options)
|
3
|
+
|
4
|
+
devise_for(:users, class_name: "Jobshop::User", module: "devise", skip: [ :sessions ])
|
5
|
+
|
6
|
+
devise_scope :user do
|
7
|
+
get "teams/:team_id/sign_in" => "sessions#new", as: :new_user_session
|
8
|
+
post "teams/:team_id/sign_in" => "sessions#create", as: :user_session
|
9
|
+
delete "teams/:team_id/sign_out" => "sessions#destroy", as: :destroy_user_session
|
10
|
+
end
|
3
11
|
|
4
12
|
resources :teams, only: [ ] do
|
5
13
|
collection do
|
@@ -10,13 +10,18 @@
|
|
10
10
|
# Make sure the secrets in this file are kept private
|
11
11
|
# if you're sharing your code publicly.
|
12
12
|
|
13
|
-
|
13
|
+
defaults: &defaults
|
14
|
+
canonical_name: "localhost"
|
14
15
|
secret_key_base: <%= SecureRandom.hex(64) %>
|
15
16
|
|
17
|
+
development:
|
18
|
+
<<: *defaults
|
19
|
+
|
16
20
|
test:
|
17
|
-
|
21
|
+
<<: *defaults
|
18
22
|
|
19
23
|
# Do not keep production secrets in the repository,
|
20
24
|
# instead read values from the environment.
|
21
25
|
production:
|
26
|
+
canonical_name: <%%= ENV["CANONICAL_NAME"] %>
|
22
27
|
secret_key_base: <%%= ENV["SECRET_KEY_BASE"] %>
|
data/lib/jobshop/version.rb
CHANGED
data/lib/jobshop.rb
CHANGED
@@ -14,10 +14,14 @@ module Jobshop
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Configuration
|
17
|
-
attr_writer :
|
17
|
+
attr_writer :canonical_name
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@canonical_name = "localhost:3000"
|
21
|
+
end
|
18
22
|
|
19
23
|
def default_url_options
|
20
|
-
{}
|
24
|
+
{ host: @canonical_name }
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jobshop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.53
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank J. Mattia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coffee-rails
|
@@ -58,28 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.
|
61
|
+
version: 4.2.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.
|
68
|
+
version: 4.2.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: material_design_lite-sass
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.
|
75
|
+
version: 1.2.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.
|
82
|
+
version: 1.2.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: pundit
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 3.
|
145
|
+
version: 3.3.0
|
146
146
|
type: :runtime
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 3.
|
152
|
+
version: 3.3.0
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: turbolinks
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -321,9 +321,11 @@ files:
|
|
321
321
|
- app/assets/stylesheets/jobshop/application.scss
|
322
322
|
- app/assets/stylesheets/jobshop/breakpoints.scss
|
323
323
|
- app/assets/stylesheets/jobshop/static.scss
|
324
|
+
- app/controllers/concerns/email_token_validation.rb
|
324
325
|
- app/controllers/concerns/registration_token_validation.rb
|
325
326
|
- app/controllers/jobshop/application_controller.rb
|
326
327
|
- app/controllers/jobshop/dashboards_controller.rb
|
328
|
+
- app/controllers/jobshop/sessions_controller.rb
|
327
329
|
- app/controllers/jobshop/setups_controller.rb
|
328
330
|
- app/controllers/jobshop/teams/lookups_controller.rb
|
329
331
|
- app/controllers/jobshop/teams/registrations_controller.rb
|
@@ -355,6 +357,7 @@ files:
|
|
355
357
|
- app/views/jobshop/setups/show.html.haml
|
356
358
|
- app/views/jobshop/teams/lookups/show.html.haml
|
357
359
|
- app/views/jobshop/teams/registrations/new.html.haml
|
360
|
+
- app/views/jobshop/teams_mailer/found_teams.html.haml
|
358
361
|
- app/views/jobshop/teams_mailer/found_teams.text.erb
|
359
362
|
- app/views/layouts/jobshop/application.html.haml
|
360
363
|
- app/views/layouts/jobshop/mailer.text.erb
|