strongmind-auth 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/concerns/jwt_utilities.rb +90 -0
- data/app/controllers/concerns/strong_mind_nav.rb +3 -0
- data/app/controllers/users/sessions_controller.rb +48 -0
- data/app/models/user_base.rb +10 -0
- data/app/views/logins/index.html.erb +10 -1
- data/app/views/users/omniauth_callbacks/failure.html.erb +126 -29
- data/config/routes.rb +3 -2
- data/lib/generators/strongmind/install_generator.rb +15 -3
- data/lib/generators/strongmind/templates/{add_uid_to_user.rb → add_uid_and_session_token_to_user.rb} +2 -1
- data/lib/strongmind/auth/version.rb +1 -1
- data/lib/strongmind/common_nav_fetcher.rb +4 -1
- metadata +7 -5
- /data/app/jobs/{rails → strongmind}/auth/application_job.rb +0 -0
- /data/app/mailers/{rails → strongmind}/auth/application_mailer.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f0de84646fc0bb458a34c17e3b6ba8e8f5754252cb5da1957822e75a7c52d4f
|
4
|
+
data.tar.gz: 3f944f111eb1b254ed97a13baf7b5e0d74401bb4edce2326ed36a94742af4499
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbba7ce9b16417331e9ec33a7b25225bb2ff3d3bc9651ac36936543197f1e95caec5c842100965b6564150c92015d46af23dfab26999db0f4847755d112eb775
|
7
|
+
data.tar.gz: 48fa3ec4e620252c4f1dfb88cd3f58df46f0054defe2f348d3282cfde28dc58829b628b6dfa5f054c5e2681b105b92b31e5c984a5711fdb68cfd1abd5b6cc7f0
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Mix-in for handling JWTs
|
4
|
+
module JwtUtilities
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def jwt_valid?(jwt, condition_key = nil, scopes = [])
|
8
|
+
begin
|
9
|
+
payload, _header = JWT.decode(jwt, public_key, true, {
|
10
|
+
verify_iat: true,
|
11
|
+
verify_iss: true,
|
12
|
+
verify_aud: true,
|
13
|
+
verify_sub: true,
|
14
|
+
algorithm: 'RS256',
|
15
|
+
leeway: 60
|
16
|
+
})
|
17
|
+
rescue JWT::DecodeError => e
|
18
|
+
Rails.logger.error e.message
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
payload = payload.with_indifferent_access
|
23
|
+
|
24
|
+
unless !scopes.empty? && payload['scope'].present? && payload['scope'].all? { |elem| scopes.include?(elem) }
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
return false unless payload['nonce'].nil?
|
29
|
+
|
30
|
+
return false unless condition_key.nil? || payload['events'].key?(condition_key)
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def public_key
|
36
|
+
Rails.cache.fetch('jwt_utilities_public_key', expires_in: 1.day) do
|
37
|
+
x5c_val = OpenIDConnect::Discovery::Provider::Config.discover!(ENV['IDENTITY_BASE_URL']).jwks.first['x5c'].first
|
38
|
+
cert = OpenSSL::X509::Certificate.new(Base64.decode64(x5c_val))
|
39
|
+
cert.public_key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def fetch_user_token_info
|
46
|
+
user_jwt(session)
|
47
|
+
end
|
48
|
+
|
49
|
+
def user_access_token(session_data)
|
50
|
+
tokens = user_jwt(session_data)
|
51
|
+
tokens[:access_token]
|
52
|
+
end
|
53
|
+
|
54
|
+
def user_jwt(session_data)
|
55
|
+
tokens = current_user.nil? ? nil : Rails.cache.read(current_user&.uid)
|
56
|
+
validate_tokens(tokens) unless tokens.nil?
|
57
|
+
|
58
|
+
if tokens.nil?
|
59
|
+
tokens = generate_tokens(session_data)
|
60
|
+
validate_tokens(tokens)
|
61
|
+
|
62
|
+
unless current_user.nil?
|
63
|
+
tokens[:expires_in] = 1.hour.to_i if tokens[:expires_in].nil?
|
64
|
+
Rails.cache.write(current_user&.uid, tokens)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
session_data[:refresh_token] = tokens[:refresh_token]
|
68
|
+
|
69
|
+
tokens
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_tokens(tokens)
|
73
|
+
return unless tokens[:error] == 'invalid_grant' || !tokens[:refresh_token]
|
74
|
+
|
75
|
+
raise RefreshTokenExpired, tokens[:error]
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_tokens(session_data)
|
79
|
+
identity_base_url = ENV['IDENTITY_BASE_URL']
|
80
|
+
identity_client_id = ENV['IDENTITY_CLIENT_ID']
|
81
|
+
response = Faraday.post("#{identity_base_url}/connect/token", {
|
82
|
+
client_id: identity_client_id,
|
83
|
+
client_secret: ENV['IDENTITY_CLIENT_SECRET'],
|
84
|
+
grant_type: 'refresh_token',
|
85
|
+
refresh_token: session_data[:refresh_token]
|
86
|
+
})
|
87
|
+
|
88
|
+
JSON.parse(response.body, symbolize_names: true)
|
89
|
+
end
|
90
|
+
end
|
@@ -12,6 +12,9 @@ module StrongMindNav
|
|
12
12
|
@theme_css = navbar[:theme_css]
|
13
13
|
rescue Strongmind::CommonNavFetcher::TokenNotFoundError, Strongmind::CommonNavFetcher::UserNotFoundError => e
|
14
14
|
Sentry.capture_exception(e)
|
15
|
+
Rails.logger.error(e)
|
16
|
+
flash[:alert] = e.inspect if Rails.env.development?
|
17
|
+
@stop_redirect = true if Rails.env.development?
|
15
18
|
render 'logins/index'
|
16
19
|
rescue Exception => e
|
17
20
|
Sentry.capture_exception(e)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Users
|
4
|
+
class RefreshTokenExpired < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class SessionsController < Devise::SessionsController
|
8
|
+
include JwtUtilities
|
9
|
+
|
10
|
+
skip_before_action :fetch_common_nav
|
11
|
+
skip_before_action :verify_authenticity_token, only: :endsession
|
12
|
+
|
13
|
+
def login
|
14
|
+
redirect_to user_strongmind_omniauth_authorize_url
|
15
|
+
end
|
16
|
+
|
17
|
+
def new
|
18
|
+
redirect_to user_strongmind_omniauth_authorize_url
|
19
|
+
end
|
20
|
+
|
21
|
+
def endsession
|
22
|
+
headers = { 'Cache-Control' => 'no-store' }
|
23
|
+
if jwt_valid?(params[:logout_token], 'http://schemas.openid.net/event/backchannel-logout')
|
24
|
+
payload, _header = JWT.decode(params[:logout_token], nil, false)
|
25
|
+
user_identity = payload['sub']
|
26
|
+
user = User.find_by(uid: user_identity)
|
27
|
+
user.invalidate_all_sessions!
|
28
|
+
render json: {}, status: :ok, headers:
|
29
|
+
else
|
30
|
+
render json: {}, status: :bad_request, headers:
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initiate_backchannel_logout
|
35
|
+
user_token_info = fetch_user_token_info
|
36
|
+
|
37
|
+
id_token_hint = user_token_info[:id_token]
|
38
|
+
token = user_token_info[:access_token]
|
39
|
+
current_user&.invalidate_all_sessions!
|
40
|
+
identity_base_url = ENV['IDENTITY_BASE_URL']
|
41
|
+
redirect_to "#{identity_base_url}/connect/endsession?id_token_hint=#{id_token_hint}", headers: {
|
42
|
+
'Content-Type' => 'application/json',
|
43
|
+
'Authorization' => "Bearer #{token}"
|
44
|
+
}, allow_other_host: true
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/app/models/user_base.rb
CHANGED
@@ -28,4 +28,14 @@ class UserBase < ApplicationRecord
|
|
28
28
|
def auth_token_cache
|
29
29
|
Rails.cache.read(uid)
|
30
30
|
end
|
31
|
+
|
32
|
+
def authenticatable_salt
|
33
|
+
return super unless session_token
|
34
|
+
|
35
|
+
"#{super}#{session_token}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def invalidate_all_sessions!
|
39
|
+
update_attribute(:session_token, SecureRandom.hex)
|
40
|
+
end
|
31
41
|
end
|
@@ -22,13 +22,22 @@
|
|
22
22
|
|
23
23
|
// Submit the form on load
|
24
24
|
window.addEventListener("load", (event) => {
|
25
|
+
<% if @stop_redirect %>
|
26
|
+
return;
|
27
|
+
<% end %>
|
25
28
|
submitForm();
|
26
29
|
});
|
27
30
|
|
28
31
|
</script>
|
29
32
|
<div id="loading">
|
33
|
+
<% flash.each do |type, message| %>
|
34
|
+
<div class="alert alert-<%= type %>"><%= message %></div>
|
35
|
+
<% end %>
|
36
|
+
<% flash.clear %>
|
30
37
|
<div class="sm-loader">
|
31
|
-
|
38
|
+
<% unless @stop_redirect %>
|
39
|
+
<img src="https://prod-backpack-ui.strongmind.com/assets/images/strongmind-loader.svg">
|
40
|
+
<% end %>
|
32
41
|
</div>
|
33
42
|
|
34
43
|
</div>
|
@@ -1,32 +1,129 @@
|
|
1
|
-
Your StrongMind identity client does not appear to be configured correctly.
|
2
|
-
<br/>
|
3
|
-
Please follow these steps:
|
4
|
-
<br/>
|
5
|
-
<br/>
|
6
1
|
<%
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
if Rails.env.development?
|
5
|
+
app_name = Rails.application.class.name.split("::").first.underscore.dasherize
|
6
|
+
if app_name == "app"
|
11
7
|
%>
|
8
|
+
Please set the name of your application in the module line of config/application.rb and restart your server.
|
9
|
+
<%
|
10
|
+
else
|
11
|
+
%>
|
12
|
+
<script>
|
13
|
+
function toggleInstructions() {
|
14
|
+
if (document.getElementById('new_app_yes').checked) {
|
15
|
+
document.getElementById('new_app_instructions').style.display = 'block';
|
16
|
+
document.getElementById('existing_app_instructions').style.display = 'none';
|
17
|
+
} else {
|
18
|
+
document.getElementById('new_app_instructions').style.display = 'none';
|
19
|
+
document.getElementById('existing_app_instructions').style.display = 'block';
|
20
|
+
}
|
21
|
+
}
|
22
|
+
</script>
|
23
|
+
<div>
|
24
|
+
Your StrongMind Identity client does not appear to be configured correctly.
|
25
|
+
</div>
|
26
|
+
<div>
|
27
|
+
Is this a brand new app that needs to be setup in StrongMind Identity?
|
28
|
+
</div>
|
29
|
+
<div class="flex">
|
30
|
+
<input type="radio" name="new_app" value="yes" id="new_app_yes" onclick="toggleInstructions()">
|
31
|
+
<label for="new_app_yes" style="margin-left: 5px">Yes</label>
|
32
|
+
</div>
|
33
|
+
<div class="flex">
|
34
|
+
<input type="radio" name="new_app" value="no" id="new_app_no" onclick="toggleInstructions()">
|
35
|
+
<label for="new_app_no" style="margin-left: 5px">No</label>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div id="existing_app_instructions" style="display: none; margin-top: 10px">
|
39
|
+
Grab the .env file from Bitwarden and place it in the root of your project. Restart your server.
|
40
|
+
</div>
|
41
|
+
<div id="new_app_instructions" style="display: none; margin-top: 10px">
|
42
|
+
<div>
|
43
|
+
Please follow these steps:
|
44
|
+
</div>
|
45
|
+
<%
|
46
|
+
local_app_url = "http://localhost:3000"
|
47
|
+
stage_app_url = "https://stage-#{app_name}.strongmind.com"
|
48
|
+
prod_app_url = "https://#{app_name}.strongmind.com"
|
49
|
+
local_redirect_url = "#{local_app_url}/users/auth/strongmind/callback"
|
50
|
+
stage_redirect_url = "#{stage_app_url}/users/auth/strongmind/callback"
|
51
|
+
prod_redirect_url = "#{prod_app_url}/users/auth/strongmind/callback"
|
52
|
+
stage_post_logout_redirect_url = "https://stage-#{app_name}.strongmind.com"
|
53
|
+
prod_post_logout_redirect_url = "https://#{app_name}.strongmind.com"
|
54
|
+
stage_backchannel_logout_url = "https://stage-#{app_name}.strongmind.com/users/endsession"
|
55
|
+
prod_backchannel_logout_url = "https://#{app_name}.strongmind.com/users/endsession"
|
56
|
+
|
57
|
+
stage_login_base_url = "https://devlogin.strongmind.com"
|
58
|
+
prod_login_base_url = "https://login.strongmind.com"
|
59
|
+
stage_secret = SecureRandom.hex(16)
|
60
|
+
prod_secret = SecureRandom.hex(16)
|
61
|
+
stage_url = "#{stage_login_base_url}/Clients/Create?"
|
62
|
+
stage_url += "ClientID=#{app_name}&"
|
63
|
+
stage_url += "RedirectURL=#{local_redirect_url}&"
|
64
|
+
stage_url += "RedirectURL=#{stage_redirect_url}&"
|
65
|
+
stage_url += "PostLogoutRedirectURL=#{stage_post_logout_redirect_url}&"
|
66
|
+
stage_url += "BackChannelLogoutUri=#{stage_backchannel_logout_url}&"
|
67
|
+
stage_url += "ClientSecret=#{stage_secret}"
|
68
|
+
|
69
|
+
prod_url = "#{prod_login_base_url}/Clients/Create?"
|
70
|
+
prod_url += "ClientID=#{app_name}&"
|
71
|
+
prod_url += "RedirectURL=#{prod_redirect_url}&"
|
72
|
+
prod_url += "PostLogoutRedirectURL=#{prod_post_logout_redirect_url}&"
|
73
|
+
prod_url += "BackChannelLogoutUri=#{prod_backchannel_logout_url}&"
|
74
|
+
prod_url += "ClientSecret=#{prod_secret}"
|
75
|
+
|
76
|
+
env_file_additions = "IDENTITY_CLIENT_ID=#{app_name}\nIDENTITY_CLIENT_SECRET=#{stage_secret}\n# Production\n#IDENTITY_CLIENT_SECRET=#{prod_secret}"
|
77
|
+
%>
|
78
|
+
|
79
|
+
<ol style="list-style: decimal">
|
80
|
+
<li>
|
81
|
+
<%= link_to "Create Client in Staging Identity Server", stage_url, { target: "_blank" } %>
|
82
|
+
</li>
|
83
|
+
<li>
|
84
|
+
<%= link_to "Create Client in Production Identity Server", prod_url, { target: "_blank" } %>
|
85
|
+
</li>
|
86
|
+
<li>
|
87
|
+
<div>
|
88
|
+
Set the following environment variables in your .env file:
|
89
|
+
</div>
|
90
|
+
<textarea style="width: 100%; height: 200px"><%= env_file_additions %></textarea>
|
91
|
+
<br/>
|
92
|
+
<button onclick="navigator.clipboard.writeText(document.querySelector('textarea').value)">
|
93
|
+
Copy to clipboard
|
94
|
+
</button>
|
95
|
+
<br/><br/>
|
96
|
+
</li>
|
97
|
+
<li>
|
98
|
+
Save the .env file into a new Bitwarden item called "<%= app_name %> .env"
|
99
|
+
</li>
|
100
|
+
<li>
|
101
|
+
Restart your server.
|
102
|
+
</li>
|
103
|
+
</ol>
|
104
|
+
</div>
|
105
|
+
<%
|
106
|
+
end
|
107
|
+
else %>
|
108
|
+
This application is not configured properly.
|
109
|
+
<br/>
|
110
|
+
Please contact your nearest engineer using a ticket.
|
111
|
+
<br/>
|
112
|
+
|
113
|
+
Provide them this information:
|
114
|
+
<%
|
115
|
+
info = {
|
116
|
+
url: request.url,
|
117
|
+
error: request.env['omniauth.error']
|
118
|
+
}
|
119
|
+
%>
|
120
|
+
<textarea style="width: 100%; height: 200px"><%= JSON.pretty_generate(info) %></textarea>
|
121
|
+
<!-- copy to clipboard -->
|
122
|
+
<button onclick="navigator.clipboard.writeText(document.querySelector('textarea').value)">
|
123
|
+
Copy to clipboard
|
124
|
+
</button>
|
12
125
|
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
<li>
|
18
|
-
<%= link_to "Create Client in Production Identity Server", prod_url %>
|
19
|
-
</li>
|
20
|
-
<li>
|
21
|
-
Set the following environment variables in your .env file:
|
22
|
-
<br/>
|
23
|
-
<br/>
|
24
|
-
<pre>
|
25
|
-
IDENTITY_CLIENT_ID=<%= app_name %><br/>IDENTITY_CLIENT_SECRET={use the secret you generated for the client}
|
26
|
-
</pre>
|
27
|
-
|
28
|
-
</li>
|
29
|
-
<li>
|
30
|
-
Restart your server.
|
31
|
-
</li>
|
32
|
-
</ol>
|
126
|
+
<div>
|
127
|
+
<%= link_to "Back to Home", "/", data: { turbo: false } %>
|
128
|
+
</div>
|
129
|
+
<% end %>
|
data/config/routes.rb
CHANGED
@@ -3,11 +3,12 @@ Rails.application.routes.draw do
|
|
3
3
|
return if defined? Rails::Generators
|
4
4
|
|
5
5
|
devise_for :users, controllers: {
|
6
|
-
omniauth_callbacks:
|
6
|
+
omniauth_callbacks: 'users/omniauth_callbacks',
|
7
|
+
sessions: 'users/sessions'
|
7
8
|
}
|
8
9
|
|
9
10
|
devise_scope :user do
|
10
|
-
|
11
|
+
get 'users/sign_out', to: 'users/sessions#initiate_backchannel_logout'
|
11
12
|
|
12
13
|
unauthenticated do
|
13
14
|
root 'logins#index', as: :unauthenticated_root
|
@@ -13,13 +13,25 @@ module Strongmind
|
|
13
13
|
|
14
14
|
def protect_app_files_and_add_nav
|
15
15
|
inject_into_file "app/controllers/application_controller.rb", after: "class ApplicationController < ActionController::Base\n" do
|
16
|
-
" include StrongMindNav
|
16
|
+
" include StrongMindNav
|
17
|
+
before_action :authenticate_user!
|
18
|
+
before_action :fetch_common_nav
|
19
|
+
|
20
|
+
rescue_from Exceptions::RefreshTokenExpiredError do
|
21
|
+
current_user&.invalidate_all_sessions!
|
22
|
+
redirect_to \"#{ENV['IDENTITY_BASE_URL']}/connect/endsession\", headers: {
|
23
|
+
'Content-Type' => 'application/json'
|
24
|
+
}, allow_other_host: true
|
25
|
+
end
|
26
|
+
|
17
27
|
# Implement the list of menu items for the application
|
18
28
|
# def menu_items
|
19
29
|
# [
|
20
30
|
# { name: 'Home', icon: 'fa-solid fa-house', path_method: :root_path }
|
21
31
|
# ]
|
22
|
-
# end
|
32
|
+
# end
|
33
|
+
|
34
|
+
"
|
23
35
|
|
24
36
|
end
|
25
37
|
end
|
@@ -38,7 +50,7 @@ devise_scope :user do
|
|
38
50
|
end
|
39
51
|
|
40
52
|
def uid_migration
|
41
|
-
migration_template "
|
53
|
+
migration_template "add_uid_and_session_token_to_user.rb", "db/migrate/add_uid_and_session_token_to_user.rb"
|
42
54
|
end
|
43
55
|
|
44
56
|
def self.next_migration_number(path)
|
data/lib/generators/strongmind/templates/{add_uid_to_user.rb → add_uid_and_session_token_to_user.rb}
RENAMED
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class
|
3
|
+
class AddUidAndSessionTokenToUser < ActiveRecord::Migration[7.0]
|
4
4
|
def change
|
5
5
|
add_column :users, :uid, :string
|
6
|
+
add_column :users, :session_token, :string
|
6
7
|
add_index :users, :uid, unique: true
|
7
8
|
end
|
8
9
|
end
|
@@ -52,7 +52,10 @@ module Strongmind
|
|
52
52
|
|
53
53
|
def token
|
54
54
|
cache_data = Rails.cache.fetch(user.uid)
|
55
|
-
|
55
|
+
cache_missing_message = " - check your caching settings (switch to file or redis)" if Rails.env.development?
|
56
|
+
unless cache_data&.key?(:access_token)
|
57
|
+
raise TokenNotFoundError, "Token not found for user #{user.uid}#{cache_missing_message}"
|
58
|
+
end
|
56
59
|
|
57
60
|
cache_data[:access_token]
|
58
61
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strongmind-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Team Belding
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -105,12 +105,14 @@ files:
|
|
105
105
|
- Rakefile
|
106
106
|
- app/assets/config/strongmind_auth_manifest.js
|
107
107
|
- app/assets/stylesheets/strongmind/auth/application.css
|
108
|
+
- app/controllers/concerns/jwt_utilities.rb
|
108
109
|
- app/controllers/concerns/strong_mind_nav.rb
|
109
110
|
- app/controllers/logins_controller.rb
|
110
111
|
- app/controllers/users/omniauth_callbacks_controller.rb
|
112
|
+
- app/controllers/users/sessions_controller.rb
|
111
113
|
- app/helpers/strongmind/auth/application_helper.rb
|
112
|
-
- app/jobs/
|
113
|
-
- app/mailers/
|
114
|
+
- app/jobs/strongmind/auth/application_job.rb
|
115
|
+
- app/mailers/strongmind/auth/application_mailer.rb
|
114
116
|
- app/models/user_base.rb
|
115
117
|
- app/views/layouts/_loading_navbar.html.erb
|
116
118
|
- app/views/logins/index.html.erb
|
@@ -119,7 +121,7 @@ files:
|
|
119
121
|
- config/routes.rb
|
120
122
|
- lib/generators/strongmind/USAGE
|
121
123
|
- lib/generators/strongmind/install_generator.rb
|
122
|
-
- lib/generators/strongmind/templates/
|
124
|
+
- lib/generators/strongmind/templates/add_uid_and_session_token_to_user.rb
|
123
125
|
- lib/generators/strongmind/templates/env
|
124
126
|
- lib/generators/strongmind/templates/user.rb
|
125
127
|
- lib/strongmind/auth.rb
|
File without changes
|
File without changes
|