strongmind-auth 1.0.3 → 1.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa3b415850df2aa96fc700cdd6f9062a2b08bd45013b3cf0eed7daface29b249
4
- data.tar.gz: f5b2460f7b9647a5ca78a077cb15fdd4ada4deec9283f4b13c25baee8cf4d1a1
3
+ metadata.gz: 29554b31cde55064956270ba9bd557e8390a49ec9a847ff417cd13e0983d0460
4
+ data.tar.gz: 534b35f4fcfa0273ec3364b1bceca1b4e0bf9f1f99c681c21d2d489b97b861b5
5
5
  SHA512:
6
- metadata.gz: a1e37eb6d57253077830cf3d34364708b3ea823272ed095ae54e348e51ecc3c1b868977c1e3e53afc2670cd98f526d8faa835e69c8f2ae25c864bf32239b0ac0
7
- data.tar.gz: 65f17555dd2cad8787ab9855f424495311a9b289a87732a508f4e2b3d3a5a4384d05a9d6f03cb371a527e9087c55f80ae94f7370fcaaa284d8e4f2146e8ea700
6
+ metadata.gz: c00798ee297949194cb98ff045e46b222bcd3a5d60d244f9f78cf5ee336299c1ba19d9c1414cd2a9f14345cd8fd6372f09769bdcc928599bf610c325552ee342
7
+ data.tar.gz: caeb996433c23a339c251f4617a525ead271377fa97d0d027ae87ae9a694cce1e07c596ebdd21f3fd3a2aab2e10ccbcc210cb0c8c9885a5c826d82e02ba80df8
data/README.md CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  Ruby gem for authentication in a rails app
4
4
 
5
- ## Usage
5
+ ## Creating a new Rails app
6
6
 
7
- 1. `rails new app --css tailwind`
8
- 1. `cd app`
9
- 1. `bundle add strongmind-auth`
10
- 1. `rails g strongmind:install`
7
+ 1. Use [Repository Dashboard](https://repository-dashboard.strongmind.com/repositories/new) to create a new repository
8
+ with the rails-template.
9
+ 1. Navigate to the repo folder in a terminal and execute `rails g strongmind:install`
11
10
  1. Move app root to authenticated root in routes. Should look like this:
12
11
  ```ruby
13
12
  authenticated :user do
@@ -15,5 +14,5 @@ Ruby gem for authentication in a rails app
15
14
  end
16
15
  ```
17
16
  1. Create a new client in identity server and `IDENTITY_CLIENT_ID` and `IDENTITY_CLIENT_SECRET` values to .env file.
18
- 1. `rails dev:cache`
19
- 1. `bin/dev`
17
+ 1. Execute `rails dev:cache` to turn on caching in development.
18
+ 1. Execute `bin/dev`
@@ -0,0 +1,26 @@
1
+ require "strongmind/common_nav_fetcher"
2
+
3
+ module StrongMindNav
4
+ extend ActiveSupport::Concern
5
+
6
+ def fetch_common_nav
7
+ begin
8
+ navbar = Strongmind::CommonNavFetcher.new(current_user, request).retrieve(menu_items)
9
+
10
+ @top_navbar_html = navbar[:top_navbar_html]
11
+ @bottom_navbar_html = navbar[:bottom_navbar_html]
12
+ @theme_css = navbar[:theme_css]
13
+ rescue Strongmind::CommonNavFetcher::TokenNotFoundError, Strongmind::CommonNavFetcher::UserNotFoundError
14
+ render 'logins/index'
15
+ rescue Faraday::TimeoutError
16
+ @top_navbar_html = render_to_string(partial: 'layouts/loading_navbar').html_safe
17
+ end
18
+ end
19
+
20
+ def menu_items
21
+ [
22
+ { name: 'Home', icon: 'fa-solid fa-house', path_method: :root_path }
23
+ ]
24
+ end
25
+
26
+ end
@@ -1,5 +1,6 @@
1
1
  class LoginsController < ApplicationController
2
2
  skip_before_action :authenticate_user!
3
+ skip_before_action :fetch_common_nav
3
4
 
4
5
  def index
5
6
  flash[:alert] = nil
@@ -3,6 +3,7 @@
3
3
  module Users
4
4
 
5
5
  class OmniauthCallbacksController < Devise::OmniauthCallbacksController
6
+ skip_before_action :fetch_common_nav
6
7
 
7
8
  def strongmind
8
9
  auth = request.env['omniauth.auth']
@@ -0,0 +1,30 @@
1
+ <a href="/" data-turbo="false">
2
+ <nav class="flex sm-top-nav">
3
+ <div class="flex-1 branding-container">
4
+ <img class="branding-logo-lg" src="https://prod-backpack-ui.strongmind.com/assets/images/sm-logo-2c-white.png"/>
5
+ <img class="branding-logo-sm" src="https://prod-backpack-ui.strongmind.com/assets/images/SMbulb.svg"/>
6
+ </div>
7
+
8
+ <div id="loading">
9
+ <canvas id="canvas" width="64" height="64"></canvas>
10
+
11
+ <script src="https://unpkg.com/@rive-app/canvas@2.9.3"></script>
12
+ <script>
13
+ const r = new rive.Rive({
14
+ src: "https://backpack.strongmind.com/assets/images/loader_dark_mode.riv",
15
+ canvas: document.getElementById("canvas"),
16
+ autoplay: true,
17
+ stateMachines: null,
18
+ onLoad: () => {
19
+ },
20
+ });
21
+ </script>
22
+ </div>
23
+
24
+ <div class="flex-1 justify-end sm-top-nav-controls">
25
+ <div class="profile-container">
26
+ <i class="fa-light fa-circle-user text-white fa-2xl"></i>
27
+ </div>
28
+ </div>
29
+ </nav>
30
+ </a>
@@ -11,9 +11,16 @@ module Strongmind
11
11
  copy_file "user.rb", "app/models/user.rb", force: true
12
12
  end
13
13
 
14
- def protect_app_files
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
- " before_action :authenticate_user!\n"
16
+ " include StrongMindNav\n before_action :authenticate_user!\n before_action :fetch_common_nav\n
17
+ # Implement the list of menu items for the application
18
+ # def menu_items
19
+ # [
20
+ # { name: 'Home', icon: 'fa-solid fa-house', path_method: :root_path }
21
+ # ]
22
+ # end"
23
+
17
24
  end
18
25
  end
19
26
 
@@ -51,6 +58,7 @@ devise_scope :user do
51
58
  def add_dotenv_file
52
59
  copy_file "env", ".env"
53
60
  end
61
+
54
62
  end
55
63
 
56
64
  end
@@ -1,5 +1,5 @@
1
1
  module Strongmind
2
2
  module Auth
3
- VERSION = "1.0.3"
3
+ VERSION = "1.0.6"
4
4
  end
5
5
  end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'platform_sdk'
4
+
5
+ module Strongmind
6
+ # This class is responsible for fetching the common navbar data from SM Central
7
+ class CommonNavFetcher
8
+ attr_reader :user, :request, :auth_client
9
+
10
+ include Rails.application.routes.url_helpers
11
+
12
+ class TokenNotFoundError < StandardError; end
13
+
14
+ class UserNotFoundError < StandardError; end
15
+
16
+ def initialize(user, request)
17
+ raise UserNotFoundError, 'User not found' unless user.present?
18
+ raise ArgumentError, 'Request not found' unless request.present?
19
+
20
+ @user = user
21
+ @request = request
22
+ @auth_client = PlatformSdk::Identity::AuthClient.new(
23
+ ENV.fetch('IDENTITY_BASE_URL'), ENV.fetch('IDENTITY_CLIENT_ID'), ENV.fetch('IDENTITY_CLIENT_SECRET')
24
+ )
25
+ end
26
+
27
+ def retrieve(menu_items)
28
+ response = fetch_navbar_data(build_nav_items(menu_items))
29
+ parse_navbar(response)
30
+ end
31
+
32
+ private
33
+
34
+ def current_page?(url)
35
+ request.fullpath == URI.parse(url).path
36
+ end
37
+
38
+ def fetch_navbar_data(nav_items)
39
+ refresh_session if auth_client.token_expired?(token)
40
+
41
+ connection.post(navbar_endpoint, nav_items.to_json, 'Authorization' => "Bearer #{token}")
42
+ end
43
+
44
+ def connection
45
+ @connection ||= Faraday.new(url: ENV.fetch('SM_CENTRAL_BASE_URL')) do |conn|
46
+ conn.options.timeout = 3
47
+ conn.response :raise_error
48
+ conn.adapter Faraday.default_adapter
49
+ conn.headers['Content-Type'] = 'application/json'
50
+ end
51
+ end
52
+
53
+ def token
54
+ cache_data = Rails.cache.fetch(user.uid)
55
+ raise TokenNotFoundError, "Token not found for user #{user.id}" unless cache_data&.key?(:access_token)
56
+
57
+ cache_data[:access_token]
58
+ end
59
+
60
+ def refresh_session
61
+ begin
62
+ session = Rails.cache.fetch(user.uid)
63
+ auth_client.refresh_session(session:)
64
+ Rails.cache.write(user.uid, session)
65
+ rescue Faraday::BadRequestError => e
66
+ Sentry.capture_exception(e, extra: { session:, request_body: request.body })
67
+ end
68
+ end
69
+
70
+ def navbar_endpoint
71
+ '/navbar'
72
+ end
73
+
74
+ def parse_navbar(response)
75
+ JSON.parse(response.body, symbolize_names: true) if response
76
+ end
77
+
78
+ def build_nav_items(menu_items)
79
+ { nav_items: menu_items.map { |item| nav_item_data(item) } }
80
+ end
81
+
82
+ def nav_item_data(item)
83
+ url = send(item[:path_method])
84
+ {
85
+ name: item[:name],
86
+ icon: item[:icon],
87
+ url:,
88
+ is_disabled: item[:feature_flag] ? !user.feature_flag_enabled?(item[:feature_flag]) : false,
89
+ is_active: current_page?(url),
90
+ is_external: false
91
+ }
92
+ end
93
+ end
94
+ 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.3
4
+ version: 1.0.6
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-13 00:00:00.000000000 Z
11
+ date: 2024-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -105,13 +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/strong_mind_nav.rb
108
109
  - app/controllers/logins_controller.rb
109
110
  - app/controllers/users/omniauth_callbacks_controller.rb
110
111
  - app/helpers/strongmind/auth/application_helper.rb
111
112
  - app/jobs/rails/auth/application_job.rb
112
113
  - app/mailers/rails/auth/application_mailer.rb
113
114
  - app/models/user_base.rb
114
- - app/views/layouts/strongmind/auth/application.html.erb
115
+ - app/views/layouts/_loading_navbar.html.erb
115
116
  - app/views/logins/index.html.erb
116
117
  - config/initializers/devise.rb
117
118
  - config/routes.rb
@@ -123,6 +124,7 @@ files:
123
124
  - lib/strongmind/auth.rb
124
125
  - lib/strongmind/auth/engine.rb
125
126
  - lib/strongmind/auth/version.rb
127
+ - lib/strongmind/common_nav_fetcher.rb
126
128
  - lib/tasks/rails/auth_tasks.rake
127
129
  - lib/tasks/strongmind/auth_tasks.rake
128
130
  homepage: https://www.strongmind.com
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Rails auth</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%#= stylesheet_link_tag "strongmind/auth/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>