bullet_train 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91587205ff146fede77d497b179accabc819d44eca37b45a073b5e97bf0fdfd0
4
- data.tar.gz: ea97e2ea8db1e6a2ce999bc06032777bc35b6d7ba6ef8f1740a408601f4a2bc7
3
+ metadata.gz: 7c456427f05a6de4ee6550f5b6e0b0631e196774e03375bbf59c5d35a9420755
4
+ data.tar.gz: c472262b19400507b36cdbad3699136464d2cdec48e1b24c5a5c011a8f5b337c
5
5
  SHA512:
6
- metadata.gz: 119ac0424011467fd3aeab95aba0213aae4711ea1246288cd38b597149a685e2874e1891371ab680a0a0f3f8e50834a2faa501670379c633c40a62a05ad5bab5
7
- data.tar.gz: 2c958dd9a290d69143dd2829018054fb5a28b35d85d3635f311cc1814087fee3ebc83d9c2f7e9dd238a3b527e24b7e251db8d0efc626ac22b082fa980775f6ca
6
+ metadata.gz: 8197df1a2ad180566d7a998dc0ba290c1c67a660c4c755f0aa6ef11ec8e2f60c97481a102d590b5a4b623e1257536b93c2007f72f0a3143829f5ab5f928fe4e9
7
+ data.tar.gz: 72ecd65e81e5d69605381baa864370cb003abd6ff7fff44708eefa351f33b7108b9fa9547e9ac1c88ca324a1aef702879dde9a5cd4c83a10f55fe896d36ff75d
@@ -0,0 +1,18 @@
1
+ class Account::TwoFactorsController < Account::ApplicationController
2
+ before_action :authenticate_user!
3
+
4
+ def create
5
+ @backup_codes = current_user.generate_otp_backup_codes!
6
+ @user = current_user
7
+
8
+ current_user.update(
9
+ otp_secret: User.generate_otp_secret,
10
+ otp_required_for_login: true
11
+ )
12
+ end
13
+
14
+ def destroy
15
+ @user = current_user
16
+ current_user.update(otp_required_for_login: false)
17
+ end
18
+ end
@@ -0,0 +1,118 @@
1
+ module Account::Controllers::Base
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include LoadsAndAuthorizesResource
6
+ include Fields::ControllerSupport
7
+
8
+ before_action :set_last_seen_at, if: proc {
9
+ user_signed_in? && (current_user.last_seen_at.nil? || current_user.last_seen_at < 1.minute.ago)
10
+ }
11
+
12
+ layout "account"
13
+
14
+ before_action :authenticate_user!
15
+ before_action :set_paper_trail_whodunnit
16
+ before_action :ensure_onboarding_is_complete_and_set_next_step
17
+ end
18
+
19
+ class_methods do
20
+ # this is a template method called by LoadsAndAuthorizesResource.
21
+ # it allows that module to understand what namespaces of a controller
22
+ # are organizing the controllers, and which are organizing the models.
23
+ def regex_to_remove_controller_namespace
24
+ /^Account::/
25
+ end
26
+ end
27
+
28
+ def adding_user_email?
29
+ is_a?(Account::Onboarding::UserEmailController)
30
+ end
31
+
32
+ def adding_user_details?
33
+ is_a?(Account::Onboarding::UserDetailsController)
34
+ end
35
+
36
+ def adding_team?
37
+ return true if request.get? && request.path == new_account_team_path
38
+ return true if request.post? && request.path == account_teams_path
39
+ false
40
+ end
41
+
42
+ def switching_teams?
43
+ return true if request.get? && request.path == account_teams_path
44
+ false
45
+ end
46
+
47
+ def managing_account?
48
+ is_a?(Account::UsersController) || self.class.module_parents.include?(Oauth)
49
+ end
50
+
51
+ def accepting_invitation?
52
+ (params[:controller] == "account/invitations") && (params[:action] == "show" || params[:action] == "accept")
53
+ end
54
+
55
+ def ensure_onboarding_is_complete_and_set_next_step
56
+ unless ensure_onboarding_is_complete
57
+ session[:after_onboarding_url] ||= request.url
58
+ end
59
+ end
60
+
61
+ def ensure_onboarding_is_complete
62
+ # This is temporary, but if we've gotten this far and `@team` is loaded, we need to ensure current_team is
63
+ # updated for the checks below. This entire concept of `current_team` is going away soon.
64
+ current_user.update(current_team: @team) if @team&.persisted?
65
+
66
+ # since the onboarding controllers are child classes of this class,
67
+ # we actually have to check to make sure we're not currently on that
68
+ # step otherwise we'll end up in an endless redirection loop.
69
+ if current_user.email_is_oauth_placeholder?
70
+ if adding_user_email?
71
+ return true
72
+ else
73
+ redirect_to edit_account_onboarding_user_email_path(current_user)
74
+ return false
75
+ end
76
+ end
77
+
78
+ # some team-related onboarding steps need to be skipped if we're in the process
79
+ # of creating a new team.
80
+ unless adding_team? || accepting_invitation?
81
+
82
+ # USER ONBOARDING STUFF
83
+ # first we make sure the user is properly onboarded.
84
+ unless current_team.present?
85
+
86
+ # don't force the user to create a team if they've already got one.
87
+ if current_user.teams.any?
88
+ current_user.update(current_team: current_user.teams.first)
89
+ else
90
+ redirect_to new_account_team_path
91
+ return false
92
+ end
93
+ end
94
+
95
+ # TEAM ONBOARDING STUFF.
96
+ # then make sure the team is properly onboarded.
97
+
98
+ # since the onboarding controllers are child classes of this class,
99
+ # we actually have to check to make sure we're not currently on that
100
+ # step otherwise we'll end up in an endless redirection loop.
101
+ unless current_user.details_provided?
102
+ if adding_user_details?
103
+ return true
104
+ else
105
+ redirect_to edit_account_onboarding_user_detail_path(current_user)
106
+ return false
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ true
113
+ end
114
+
115
+ def set_last_seen_at
116
+ current_user.update_attribute(:last_seen_at, Time.current)
117
+ end
118
+ end
@@ -0,0 +1,119 @@
1
+ module Controllers::Base
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ # these are common for authentication workflows.
6
+ include InvitationOnlyHelper
7
+ include InvitationsHelper
8
+
9
+ include DeviseCurrentAttributes
10
+
11
+ around_action :set_locale
12
+ layout :layout_by_resource
13
+
14
+ before_action { @updating = request.headers["X-Cable-Ready"] == "update" }
15
+
16
+ # TODO Extract this into an optional `bullet_train-sentry` package.
17
+ before_action :set_sentry_context
18
+
19
+ skip_before_action :verify_authenticity_token, if: -> { controller_name == "sessions" && action_name == "create" }
20
+
21
+ rescue_from CanCan::AccessDenied do |exception|
22
+ if current_user.nil?
23
+ respond_to do |format|
24
+ format.html do
25
+ session["user_return_to"] = request.path
26
+ redirect_to [:new, :user, :session], alert: exception.message
27
+ end
28
+ end
29
+ elsif current_user.teams.none?
30
+ respond_to do |format|
31
+ format.html { redirect_to [:new, :account, :team], alert: exception.message }
32
+ end
33
+ else
34
+ respond_to do |format|
35
+ # TODO we do this for now because it ensures `current_team` doesn't remain set in an invalid state.
36
+ format.html { redirect_to [:account, current_user.teams.first], alert: exception.message }
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # this is an ugly hack, but it's what is recommended at
43
+ # https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts
44
+ def layout_by_resource
45
+ if devise_controller?
46
+ "devise"
47
+ else
48
+ "public"
49
+ end
50
+ end
51
+
52
+ def after_sign_in_path_for(resource_or_scope)
53
+ resource = resource_or_scope.class.name.downcase
54
+ stored_location_for(resource) || account_dashboard_path
55
+ end
56
+
57
+ def after_sign_up_path_for(resource_or_scope)
58
+ resource = resource_or_scope.class.name.downcase
59
+ stored_location_for(resource) || account_dashboard_path
60
+ end
61
+
62
+ def current_team
63
+ helpers.current_team
64
+ end
65
+
66
+ def current_membership
67
+ helpers.current_membership
68
+ end
69
+
70
+ def current_locale
71
+ helpers.current_locale
72
+ end
73
+
74
+ def enforce_invitation_only
75
+ if invitation_only?
76
+ unless helpers.invited?
77
+ redirect_to [:account, :teams], notice: t("teams.notifications.invitation_only")
78
+ end
79
+ end
80
+ end
81
+
82
+ def set_locale
83
+ I18n.locale = [
84
+ current_user&.locale,
85
+ current_user&.current_team&.locale,
86
+ http_accept_language.compatible_language_from(I18n.available_locales),
87
+ I18n.default_locale.to_s
88
+ ].compact.find { |potential_locale| I18n.available_locales.include?(potential_locale.to_sym) }
89
+ yield
90
+ I18n.locale = I18n.default_locale
91
+ end
92
+
93
+ # Whitelist the account namespace and prevent JavaScript
94
+ # embedding when passing paths as parameters in links.
95
+ def only_allow_path(path)
96
+ return if path.nil?
97
+ account_namespace_regexp = /^\/account\/*+/
98
+ scheme = URI.parse(path).scheme
99
+ return nil unless path.match?(account_namespace_regexp) && scheme != "javascript"
100
+ path
101
+ end
102
+
103
+ # TODO Extract this into an optional `bullet_train-sentry` package.
104
+ def set_sentry_context
105
+ return unless ENV["SENTRY_DSN"]
106
+
107
+ Sentry.configure_scope do |scope|
108
+ scope.set_user(id: current_user.id, email: current_user.email) if current_user
109
+
110
+ scope.set_context(
111
+ "request",
112
+ {
113
+ url: request.url,
114
+ params: params.to_unsafe_h
115
+ }
116
+ )
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,13 @@
1
+ module DeviseCurrentAttributes
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :set_current_user
6
+ end
7
+
8
+ def set_current_user
9
+ if current_user
10
+ Current.user = current_user
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ $("#two-factor").html("<%= j render partial: "devise/registrations/two_factor"%>");
@@ -0,0 +1 @@
1
+ $("#two-factor").html("<%= j render partial: "devise/registrations/two_factor"%>");
@@ -0,0 +1 @@
1
+ <%= render "themes/#{current_theme}/layouts/account" %>
@@ -0,0 +1 @@
1
+ <%= render "themes/#{current_theme}/layouts/devise" %>
@@ -1,3 +1,3 @@
1
1
  module BulletTrain
2
- VERSION = "1.0.7"
2
+ VERSION = "1.0.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
@@ -40,13 +40,17 @@ files:
40
40
  - app/controllers/account/onboarding/user_details_controller.rb
41
41
  - app/controllers/account/onboarding/user_email_controller.rb
42
42
  - app/controllers/account/teams_controller.rb
43
+ - app/controllers/account/two_factors_controller.rb
43
44
  - app/controllers/account/users_controller.rb
45
+ - app/controllers/concerns/account/controllers/base.rb
44
46
  - app/controllers/concerns/account/invitations/controller_base.rb
45
47
  - app/controllers/concerns/account/memberships/controller_base.rb
46
48
  - app/controllers/concerns/account/onboarding/user_details/controller_base.rb
47
49
  - app/controllers/concerns/account/onboarding/user_email/controller_base.rb
48
50
  - app/controllers/concerns/account/teams/controller_base.rb
49
51
  - app/controllers/concerns/account/users/controller_base.rb
52
+ - app/controllers/concerns/controllers/base.rb
53
+ - app/controllers/concerns/devise_current_attributes.rb
50
54
  - app/controllers/concerns/registrations/controller_base.rb
51
55
  - app/controllers/concerns/sessions/controller_base.rb
52
56
  - app/controllers/registrations_controller.rb
@@ -109,6 +113,8 @@ files:
109
113
  - app/views/account/teams/new.html.erb
110
114
  - app/views/account/teams/show.html.erb
111
115
  - app/views/account/teams/show.json.jbuilder
116
+ - app/views/account/two_factors/create.js.erb
117
+ - app/views/account/two_factors/destroy.js.erb
112
118
  - app/views/account/users/_breadcrumbs.html.erb
113
119
  - app/views/account/users/_form.html.erb
114
120
  - app/views/account/users/edit.html.erb
@@ -128,6 +134,8 @@ files:
128
134
  - app/views/devise/shared/_links.html.erb
129
135
  - app/views/devise/shared/_oauth.html.erb
130
136
  - app/views/devise/unlocks/new.html.erb
137
+ - app/views/layouts/account.html.erb
138
+ - app/views/layouts/devise.html.erb
131
139
  - config/locales/en/devise.en.yml
132
140
  - config/locales/en/invitations.en.yml
133
141
  - config/locales/en/memberships.en.yml