propel_authentication 0.1.4 → 0.2.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -2
  3. data/README.md +6 -6
  4. data/lib/generators/propel_authentication/install_generator.rb +135 -153
  5. data/lib/generators/propel_authentication/templates/application_mailer.rb +6 -0
  6. data/lib/generators/propel_authentication/templates/auth/passwords_controller.rb.tt +84 -78
  7. data/lib/generators/propel_authentication/templates/auth/signup_controller.rb.tt +242 -0
  8. data/lib/generators/propel_authentication/templates/{tokens_controller.rb.tt → auth/tokens_controller.rb.tt} +39 -22
  9. data/lib/generators/propel_authentication/templates/auth_mailer.rb +3 -1
  10. data/lib/generators/propel_authentication/templates/authenticatable.rb +8 -2
  11. data/lib/generators/propel_authentication/templates/concerns/confirmable.rb +1 -1
  12. data/lib/generators/propel_authentication/templates/concerns/lockable.rb +4 -2
  13. data/lib/generators/propel_authentication/templates/concerns/{propel_authentication.rb → propel_authentication_concern.rb} +33 -3
  14. data/lib/generators/propel_authentication/templates/concerns/recoverable.rb +16 -6
  15. data/lib/generators/propel_authentication/templates/core/configuration_methods.rb +104 -64
  16. data/lib/generators/propel_authentication/templates/db/seeds.rb +50 -4
  17. data/lib/generators/propel_authentication/templates/doc/signup_flow.md +315 -0
  18. data/lib/generators/propel_authentication/templates/models/agency.rb.tt +13 -0
  19. data/lib/generators/propel_authentication/templates/models/agent.rb.tt +13 -0
  20. data/lib/generators/propel_authentication/templates/{invitation.rb → models/invitation.rb.tt} +6 -0
  21. data/lib/generators/propel_authentication/templates/models/organization.rb.tt +12 -0
  22. data/lib/generators/propel_authentication/templates/{user.rb → models/user.rb.tt} +5 -0
  23. data/lib/generators/propel_authentication/templates/propel_authentication.rb.tt +94 -9
  24. data/lib/generators/propel_authentication/templates/routes/auth_routes.rb.tt +55 -0
  25. data/lib/generators/propel_authentication/templates/services/auth_notification_service.rb +3 -3
  26. data/lib/generators/propel_authentication/templates/test/concerns/confirmable_test.rb.tt +34 -10
  27. data/lib/generators/propel_authentication/templates/test/concerns/propel_authentication_test.rb.tt +1 -1
  28. data/lib/generators/propel_authentication/templates/test/concerns/recoverable_test.rb.tt +4 -4
  29. data/lib/generators/propel_authentication/templates/test/controllers/auth/lockable_integration_test.rb.tt +18 -15
  30. data/lib/generators/propel_authentication/templates/test/controllers/auth/password_reset_integration_test.rb.tt +38 -40
  31. data/lib/generators/propel_authentication/templates/test/controllers/auth/signup_controller_test.rb.tt +201 -0
  32. data/lib/generators/propel_authentication/templates/test/controllers/auth/tokens_controller_test.rb.tt +33 -25
  33. data/lib/generators/propel_authentication/templates/test/mailers/auth_mailer_test.rb.tt +51 -36
  34. data/lib/generators/propel_authentication/templates/views/auth_mailer/email_confirmation.html.erb +2 -2
  35. data/lib/generators/propel_authentication/templates/views/auth_mailer/email_confirmation.text.erb +1 -1
  36. data/lib/generators/propel_authentication/test/generators/authentication/install_generator_test.rb +4 -4
  37. data/lib/generators/propel_authentication/test/generators/authentication/uninstall_generator_test.rb +1 -1
  38. data/lib/generators/propel_authentication/test/integration/generator_integration_test.rb +1 -1
  39. data/lib/generators/propel_authentication/test/integration/multi_version_generator_test.rb +13 -12
  40. data/lib/generators/propel_authentication/unpack_generator.rb +19 -15
  41. data/lib/propel_authentication.rb +1 -1
  42. metadata +14 -11
  43. data/lib/generators/propel_authentication/templates/agency.rb +0 -7
  44. data/lib/generators/propel_authentication/templates/agent.rb +0 -7
  45. data/lib/generators/propel_authentication/templates/auth/base_passwords_controller.rb.tt +0 -99
  46. data/lib/generators/propel_authentication/templates/auth/base_tokens_controller.rb.tt +0 -90
  47. data/lib/generators/propel_authentication/templates/organization.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b1f57ecf3f4af5949e584a1a3999763ba8bbf5b558bfb0bbd8505de249c2603
4
- data.tar.gz: d83ba00e83a944dfafac07fadc250cded1c6ba631108d91e5cd46c13c8592703
3
+ metadata.gz: 22860db42c802dc6a34029c311149badcf95f0b9c54a2f83767bf4c2f1c62618
4
+ data.tar.gz: 30c016587b4500344ad0a6a95feeef37a12cee54a7addd4f912c67fc5b8f4ca3
5
5
  SHA512:
6
- metadata.gz: a8fcdcbd5e287c80e989d9c7ebca67ca43b2eb5ee894aa330de5c3bbb1e08c25776837d24345b3c96bd04055cd960a8b433dd79dc912f1b316bec0a0fb45cf1e
7
- data.tar.gz: f90e403196ba6e4df6adae2359331fbb82354b890ed8b2594d702d24f19318d65ad0e87d498530bd9848ced16a490fc6f5e006221a08f68539c364e12f17aeef
6
+ metadata.gz: 7da4c75f8d12fce6ad7a0686d2ac6fca6146df044e0b8d8bf6f73acb812f851298c270529cb8c9bd6ef10acb992c0a2b62711182ea92caf7deef06bad084d627
7
+ data.tar.gz: f94d8b1ec7dfaad482db03aff177dee93af78ef132bd89634af780044f5907f0aa95afe96971540af058f364dfaf4b410f1aaca02311b0b51970b0d83ff6fbf6
data/CHANGELOG.md CHANGED
@@ -13,7 +13,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
  - Session management and device tracking
14
14
  - Advanced password policies
15
15
 
16
- ## [0.1.4] - 2025-01-23
16
+ ## [0.2.0] - 2025-09-02
17
+
18
+ ### BREAKING CHANGES
19
+ - **Configuration ownership**: `agency_tenancy` configuration moved from PropelApi to PropelAuthentication
20
+ - Update config files: `PropelApi.configuration.agency_tenancy` → `PropelAuthentication.configuration.agency_tenancy`
21
+ - PropelAuthentication now owns all tenancy model configuration
22
+ - **Frontend URL configuration**: No longer allows nil values
23
+ - Configuration hierarchy: Rails credentials → ENV variables → explicit fallbacks
24
+ - `frontend_url` must be configured (no nil defaults)
25
+
26
+ ### Added
27
+ - **Configurable tenancy requirements**: New fine-grained control over API behavior
28
+ - `require_organization_id` (default: false) - Controls whether explicit organization_id is required in API requests
29
+ - `require_user_id` (default: false) - Controls whether explicit user_id is required in API requests
30
+ - Developer-friendly defaults enable auto-assignment while allowing strict enterprise security
31
+ - **Enhanced User model**: Complete multi-agency support
32
+ - Added `has_many :agencies, through: :agents` relationship for agency access
33
+ - Enhanced JSON facets with comprehensive field sets including authentication status
34
+ - Short facet now includes `:status` field for user state tracking
35
+ - Details facet includes all authentication fields with proper association includes
36
+
37
+ ### Fixed
38
+ - **Authentication namespace conflict resolved** - Renamed authentication concern to prevent module name collision
39
+ - `PropelAuthentication` concern renamed to `PropelAuthenticationConcern`
40
+ - Eliminates conflict between authentication controller concern and PropelAuthentication configuration module
41
+ - Updated all controller templates and generated files
42
+ - Enhanced method visibility for better API design
43
+ - **Email confirmation workflow**: Fixed multipart email handling and token generation timing
44
+ - **Account locking idempotency**: `lock_account!` method now properly handles race conditions
45
+ - **Configuration consistency**: Unified tenancy model ownership under PropelAuthentication
46
+
47
+ ### Improved
48
+ - **JWT token security**: Removed agency_ids from JWT payload for better security (looked up in real-time)
49
+ - **User facet completeness**: Details facet now includes all relevant authentication and profile fields
50
+ - **Authentication concern API design** - Better method organization and access patterns
51
+ - `authenticate_user` - Public method for `before_action` callbacks
52
+ - `current_user` - Public method for accessing authenticated user
53
+ - `extract_jwt_token` - Public method for custom authentication scenarios (email notifications, audit logging, token refresh)
54
+ - Clean separation between public API and internal implementation
55
+
56
+ ## [0.1.4] - 2025-08-15
17
57
 
18
58
  ### Fixed
19
59
  - **Critical generator extraction issue** - Core infrastructure files now properly extracted during installation
@@ -42,7 +82,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42
82
  - Proper error handling and status codes
43
83
  - Enhanced test coverage with behavior-driven assertions
44
84
 
45
- ## [0.1.3] - 2025-01-XX
85
+ ## [0.1.3] - 2025-07-22
46
86
 
47
87
  ### Added
48
88
  - **Self-extracting generator gem architecture** - Install temporarily, extract code, remove dependency
@@ -85,3 +125,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
85
125
  - **Full customization control** - modify any authentication component
86
126
  - **Standard Rails patterns** - follows established conventions
87
127
  - **Easy maintenance** - no hidden gem complexity in production
128
+
data/README.md CHANGED
@@ -10,7 +10,7 @@ PropelAuthentication is designed as a **self-extracting generator gem** followin
10
10
 
11
11
  ```ruby
12
12
  # In your Gemfile
13
- gem 'propel_authentication', '~> 0.1.4'
13
+ gem 'propel_authentication', '~> 0.2.0'
14
14
  ```
15
15
 
16
16
  ### Step 2: Bundle Install
@@ -128,7 +128,7 @@ end
128
128
 
129
129
  # In your controllers
130
130
  class ApplicationController < ActionController::API
131
- include PropelAuthentication # Authentication helpers
131
+ include PropelAuthenticationConcernConcern # Authentication helpers
132
132
  include RackSessionDisable # Disable Rails sessions for API-only apps
133
133
 
134
134
  # Use authenticate_user to protect endpoints
@@ -258,7 +258,7 @@ After installation, PropelAuthentication creates:
258
258
  ### Controllers
259
259
  - `app/controllers/auth/tokens_controller.rb` - Login, logout, user info
260
260
  - `app/controllers/auth/passwords_controller.rb` - Password reset functionality
261
- - `app/controllers/concerns/propel_authentication.rb` - Authentication helpers
261
+ - `app/controllers/concerns/propel_authentication_concern.rb` - Authentication helpers
262
262
  - `app/controllers/concerns/rack_session_disable.rb` - Session management for APIs
263
263
 
264
264
  ### Services
@@ -300,7 +300,7 @@ After installation, PropelAuthentication creates:
300
300
 
301
301
  ```ruby
302
302
  class Api::V1::UsersController < ApplicationController
303
- include PropelAuthentication
303
+ include PropelAuthenticationConcern
304
304
  before_action :authenticate_user
305
305
 
306
306
  def index
@@ -374,7 +374,7 @@ PropelAuthentication integrates seamlessly with other PropelRails gems:
374
374
  ```ruby
375
375
  # Generated API controllers automatically include authentication
376
376
  class Api::V1::ApiController < ApplicationController
377
- include PropelAuthentication
377
+ include PropelAuthenticationConcern
378
378
  before_action :authenticate_user
379
379
 
380
380
  # Your API methods here
@@ -412,7 +412,7 @@ bundle exec rake test
412
412
 
413
413
  ## Version History
414
414
 
415
- ### 0.1.4 (Current)
415
+ ### 0.2.0 (Current)
416
416
  - Fixed generator extraction issues
417
417
  - Enhanced JWT authentication with proper secret handling
418
418
  - Complete test suite passing
@@ -34,7 +34,7 @@ module PropelAuthentication
34
34
  desc "Generate JWT-based authentication system with configurable URL architecture"
35
35
 
36
36
  def copy_jwt_initializer
37
- initialize_propel_auth_settings
37
+ determine_configuration
38
38
 
39
39
  if behavior == :revoke
40
40
  remove_file "config/initializers/propel_authentication.rb"
@@ -46,14 +46,15 @@ module PropelAuthentication
46
46
  end
47
47
  end
48
48
 
49
-
50
-
51
49
  def copy_authentication_models
52
- copy_file "user.rb", "app/models/user.rb"
53
- copy_file "organization.rb", "app/models/organization.rb"
54
- copy_file "agency.rb", "app/models/agency.rb"
55
- copy_file "agent.rb", "app/models/agent.rb"
56
- copy_file "invitation.rb", "app/models/invitation.rb"
50
+ # Detect rendering engine for conditional facet generation
51
+ @rendering_engine = detect_rendering_engine
52
+
53
+ template "models/user.rb.tt", "app/models/user.rb"
54
+ template "models/organization.rb.tt", "app/models/organization.rb"
55
+ template "models/agency.rb.tt", "app/models/agency.rb"
56
+ template "models/agent.rb.tt", "app/models/agent.rb"
57
+ template "models/invitation.rb.tt", "app/models/invitation.rb"
57
58
  end
58
59
 
59
60
  def copy_authentication_concerns
@@ -61,20 +62,15 @@ module PropelAuthentication
61
62
  copy_file "concerns/lockable.rb", "app/models/concerns/lockable.rb"
62
63
  copy_file "concerns/recoverable.rb", "app/models/concerns/recoverable.rb"
63
64
  copy_file "concerns/confirmable.rb", "app/models/concerns/confirmable.rb"
64
- copy_file "concerns/propel_authentication.rb", "app/controllers/concerns/propel_authentication.rb"
65
+ copy_file "concerns/propel_authentication_concern.rb", "app/controllers/concerns/propel_authentication_concern.rb"
65
66
  copy_file "concerns/rack_session_disable.rb", "app/controllers/concerns/rack_session_disable.rb"
66
67
  end
67
68
 
68
69
  def copy_jwt_controllers
69
- if auth_namespaced?
70
- template "auth/base_tokens_controller.rb.tt", "app/controllers/#{auth_namespace_path}/auth/base_tokens_controller.rb"
71
- template "auth/base_passwords_controller.rb.tt", "app/controllers/#{auth_namespace_path}/auth/base_passwords_controller.rb"
72
- create_versioned_controller(@auth_version || 'v1', 'tokens', controller_directory)
73
- create_versioned_controller(@auth_version || 'v1', 'passwords', controller_directory)
74
- else
75
- template "tokens_controller.rb.tt", "#{controller_directory}/tokens_controller.rb"
76
- template "auth/passwords_controller.rb.tt", "#{controller_directory}/passwords_controller.rb"
77
- end
70
+ # Generate direct controllers with dynamic file paths (no inheritance)
71
+ template "auth/tokens_controller.rb.tt", controller_file_path('tokens')
72
+ template "auth/passwords_controller.rb.tt", controller_file_path('passwords')
73
+ template "auth/signup_controller.rb.tt", controller_file_path('signup')
78
74
  end
79
75
 
80
76
  def copy_email_infrastructure
@@ -89,9 +85,14 @@ module PropelAuthentication
89
85
  end
90
86
  end
91
87
 
88
+ def copy_documentation
89
+ copy_file "doc/signup_flow.md", "doc/signup_flow.md"
90
+ end
91
+
92
92
  def copy_authentication_tests
93
93
  template "user_test.rb.tt", "test/models/user_test.rb"
94
94
  template "test/controllers/auth/tokens_controller_test.rb.tt", "test/controllers/auth/tokens_controller_test.rb"
95
+ template "test/controllers/auth/signup_controller_test.rb.tt", "test/controllers/auth/signup_controller_test.rb"
95
96
  template "test/mailers/auth_mailer_test.rb.tt", "test/mailers/auth_mailer_test.rb"
96
97
  copy_file "test/mailers/previews/auth_mailer_preview.rb", "test/mailers/previews/auth_mailer_preview.rb"
97
98
  end
@@ -120,7 +121,19 @@ module PropelAuthentication
120
121
  end
121
122
 
122
123
  def add_authentication_routes
123
- route generate_routes_content
124
+ routes_file = File.join(destination_root, "config/routes.rb")
125
+ return unless File.exist?(routes_file)
126
+
127
+ routes_content = File.read(routes_file)
128
+
129
+ # Check if authentication routes already exist
130
+ if authentication_routes_exist?(routes_content)
131
+ say "Authentication routes already exist, skipping route generation", :yellow
132
+ return
133
+ end
134
+
135
+ # Use dedicated routes template for clean separation of concerns
136
+ route template_file_for_routes
124
137
  end
125
138
 
126
139
  def copy_authentication_migrations
@@ -166,12 +179,12 @@ module PropelAuthentication
166
179
  say "• Run: rails test", :blue
167
180
  say "• Optional: Remove 'propel_auth' from Gemfile (system is fully extracted)", :cyan
168
181
 
169
- if auth_namespaced?
182
+ if @auth_namespace.present? || @auth_version.present? || @auth_scope.present?
170
183
  say "• Routes: #{auth_route_prefix}/*", :blue
171
- say "• Controllers: #{controller_namespace}::*", :blue
184
+ say "• Controllers: #{controller_namespace('tokens')}*", :blue
172
185
  else
173
186
  say "• Routes: /login, /logout, /me", :blue
174
- say "• Controllers: Auth::*", :blue
187
+ say "• Controllers: TokensController, PasswordsController, etc.", :blue
175
188
  end
176
189
 
177
190
  say "\n🎨 Customization:", :bold
@@ -184,75 +197,34 @@ module PropelAuthentication
184
197
 
185
198
  private
186
199
 
187
- # Helper methods for authentication URL structure
188
- def auth_namespaced?
189
- @auth_namespace.present? || @auth_version.present?
190
- end
191
-
192
- def auth_namespace_path
193
- return '' unless auth_namespaced?
194
- path_parts = []
195
- path_parts << @auth_namespace if @auth_namespace.present?
196
- path_parts << @auth_version if @auth_version.present?
197
- path_parts.join('/')
198
- end
199
-
200
- def controller_namespace
201
- auth_controller_namespace
202
- end
203
-
204
- def controller_directory
205
- auth_controller_directory
206
- end
207
-
208
- def api_only_app?
209
- # Check if this is a Rails API-only application
210
- Rails.application.config.respond_to?(:api_only) && Rails.application.config.api_only
211
- end
212
-
213
- # Path helper methods for tests
214
- def login_path_helper
215
- if auth_namespaced?
216
- "'#{auth_route_prefix}/login'"
200
+ # Check if authentication routes already exist in routes file
201
+ def authentication_routes_exist?(routes_content)
202
+ # Check for key authentication routes based on our configuration
203
+ if @auth_namespace.present? && @auth_version.present? && @auth_scope.present?
204
+ # Check for api/v1/auth/login pattern
205
+ routes_content.match?(/namespace\s+:#{@auth_namespace}\s+do.*?namespace\s+:#{@auth_version}\s+do.*?namespace\s+:#{@auth_scope}\s+do.*?post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/m)
206
+ elsif @auth_namespace.present? && @auth_version.present?
207
+ # Check for api/v1/login pattern
208
+ routes_content.match?(/namespace\s+:#{@auth_namespace}\s+do.*?namespace\s+:#{@auth_version}\s+do.*?post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/m)
209
+ elsif @auth_namespace.present? && @auth_scope.present?
210
+ # Check for api/auth/login pattern
211
+ routes_content.match?(/namespace\s+:#{@auth_namespace}\s+do.*?namespace\s+:#{@auth_scope}\s+do.*?post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/m)
212
+ elsif @auth_scope.present?
213
+ # Check for auth/login pattern
214
+ routes_content.match?(/namespace\s+:#{@auth_scope}\s+do.*?post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/m)
215
+ elsif @auth_namespace.present?
216
+ # Check for api/login pattern
217
+ routes_content.match?(/namespace\s+:#{@auth_namespace}\s+do.*?post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/m)
217
218
  else
218
- "'/login'"
219
+ # Check for root-level login route
220
+ routes_content.match?(/post\s+['"]login['"],?\s+to:\s+['"]tokens#create['"], as: :login/)
219
221
  end
220
222
  end
221
223
 
222
- def me_path_helper
223
- if auth_namespaced?
224
- "'#{auth_route_prefix}/me'"
225
- else
226
- "'/me'"
227
- end
228
- end
229
-
230
- def logout_path_helper
231
- if auth_namespaced?
232
- "'#{auth_route_prefix}/logout'"
233
- else
234
- "'/logout'"
235
- end
236
- end
237
-
238
- def unlock_path_helper
239
- if auth_namespaced?
240
- "'#{auth_route_prefix}/unlock'"
241
- else
242
- "'/unlock'"
243
- end
244
- end
245
-
246
- def password_reset_path_helper
247
- if auth_namespaced?
248
- "'#{auth_route_prefix}/reset'"
249
- else
250
- "'/reset'"
251
- end
252
- end
253
-
254
- def reset_path_helper
255
- password_reset_path_helper
224
+ # Render authentication routes template to string
225
+ def template_file_for_routes
226
+ source_path = find_in_source_paths("routes/auth_routes.rb.tt")
227
+ ERB.new(File.read(source_path), trim_mode: '-').result(binding)
256
228
  end
257
229
 
258
230
  def add_gem_if_missing(gem_name, version_requirement = nil, options = {})
@@ -284,71 +256,7 @@ module PropelAuthentication
284
256
  def migration_exists?(migration_name)
285
257
  Dir.glob("#{destination_root}/db/migrate/*_#{migration_name}.rb").any?
286
258
  end
287
-
288
- def generate_routes_content
289
- if auth_namespaced?
290
- route_lines = ["# JWT Authentication routes for #{auth_route_prefix}"]
291
-
292
- # Build namespace opening
293
- namespace_parts = []
294
- namespace_parts << @auth_namespace if @auth_namespace.present?
295
- namespace_parts << @auth_version if @auth_version.present?
296
-
297
- namespace_parts.each_with_index do |part, index|
298
- indent = " " * index
299
- route_lines << "#{indent}namespace :#{part} do"
300
- end
301
-
302
- # Add authentication routes directly in namespace (no nested /auth/)
303
- route_indent = " " * namespace_parts.length
304
- route_lines << "#{route_indent}post 'login', to: 'auth/tokens#create'"
305
- route_lines << "#{route_indent}get 'me', to: 'auth/tokens#me'"
306
- route_lines << "#{route_indent}delete 'logout', to: 'auth/tokens#destroy'"
307
- route_lines << "#{route_indent}post 'unlock', to: 'auth/tokens#unlock'"
308
- route_lines << "#{route_indent}post 'reset', to: 'auth/passwords#create'"
309
- route_lines << "#{route_indent}get 'reset', to: 'auth/passwords#show'"
310
- route_lines << "#{route_indent}patch 'reset', to: 'auth/passwords#update'"
311
-
312
- # Build namespace closing
313
- namespace_parts.length.times do |index|
314
- indent = " " * (namespace_parts.length - 1 - index)
315
- route_lines << "#{indent}end"
316
- end
317
-
318
- route_lines.join("\n")
319
- else
320
- <<~ROUTES
321
- # JWT Authentication routes
322
- post 'login', to: 'auth/tokens#create'
323
- get 'me', to: 'auth/tokens#me'
324
- delete 'logout', to: 'auth/tokens#destroy'
325
- post 'unlock', to: 'auth/tokens#unlock'
326
- post 'reset', to: 'auth/passwords#create'
327
- get 'reset', to: 'auth/passwords#show'
328
- patch 'reset', to: 'auth/passwords#update'
329
- ROUTES
330
- end
331
- end
332
-
333
- def create_versioned_controller(version, controller_type, directory)
334
- case controller_type
335
- when 'tokens'
336
- controller_content = <<~RUBY
337
- # Generated versioned controller for API #{version}
338
- class Api::#{version.camelize}::Auth::TokensController < Api::Auth::BaseTokensController
339
- end
340
- RUBY
341
- when 'passwords'
342
- controller_content = <<~RUBY
343
- # Generated versioned controller for API #{version}
344
- class Api::#{version.camelize}::Auth::PasswordsController < Api::Auth::BasePasswordsController
345
- end
346
- RUBY
347
- end
348
-
349
- create_file "#{directory}/#{controller_type}_controller.rb", controller_content
350
- end
351
-
259
+
352
260
  # Fixture content methods
353
261
  def organizations_fixture
354
262
  <<~FIXTURE
@@ -451,17 +359,70 @@ module PropelAuthentication
451
359
  organization: acme_org
452
360
  created_at: <%= 10.days.ago %>
453
361
  updated_at: <%= 2.days.ago %>
362
+
363
+ sales_agency:
364
+ name: "Sales Department"
365
+ organization: acme_org
366
+ created_at: <%= 9.days.ago %>
367
+ updated_at: <%= 2.days.ago %>
368
+
369
+ tech_agency:
370
+ name: "Tech Solutions"
371
+ organization: tech_startup
372
+ created_at: <%= 8.days.ago %>
373
+ updated_at: <%= 1.day.ago %>
374
+
375
+ support_agency:
376
+ name: "Support Team"
377
+ organization: tech_startup
378
+ created_at: <%= 7.days.ago %>
379
+ updated_at: <%= 1.day.ago %>
454
380
  FIXTURE
455
381
  end
456
382
 
457
383
  def agents_fixture
458
384
  <<~FIXTURE
459
- marketing_agent:
385
+ john_marketing_agent:
460
386
  user: john_user
461
387
  agency: marketing_agency
462
388
  role: "manager"
463
389
  created_at: <%= 8.days.ago %>
464
390
  updated_at: <%= 1.day.ago %>
391
+
392
+ confirmed_sales_agent:
393
+ user: confirmed_user
394
+ agency: sales_agency
395
+ role: "analyst"
396
+ created_at: <%= 7.days.ago %>
397
+ updated_at: <%= 1.day.ago %>
398
+
399
+ locked_marketing_agent:
400
+ user: locked_user
401
+ agency: marketing_agency
402
+ role: "coordinator"
403
+ created_at: <%= 6.days.ago %>
404
+ updated_at: <%= 1.day.ago %>
405
+
406
+ jane_tech_agent:
407
+ user: jane_user
408
+ agency: tech_agency
409
+ role: "developer"
410
+ created_at: <%= 5.days.ago %>
411
+ updated_at: <%= 1.day.ago %>
412
+
413
+ expired_support_agent:
414
+ user: expired_confirmation_user
415
+ agency: support_agency
416
+ role: "specialist"
417
+ created_at: <%= 4.days.ago %>
418
+ updated_at: <%= 1.day.ago %>
419
+
420
+ locked_sales_agent:
421
+ user: locked_user
422
+ agency: sales_agency
423
+ role: "trainee"
424
+ created_at: <%= 3.days.ago %>
425
+ updated_at: <%= 1.day.ago %>
465
426
  FIXTURE
466
427
  end
467
428
 
@@ -478,5 +439,26 @@ module PropelAuthentication
478
439
  updated_at: <%= 3.days.ago %>
479
440
  FIXTURE
480
441
  end
442
+
443
+ def detect_rendering_engine
444
+ # Check for common rendering engines in order of preference
445
+ propel_facets_path = File.join(destination_root, 'config/initializers/propel_facets.rb')
446
+ return 'json_facet' if File.exist?(propel_facets_path)
447
+ return 'graphiti' if defined?(Graphiti) || gem_present?('graphiti')
448
+ return 'blueprinter' if defined?(Blueprinter) || gem_present?('blueprinter')
449
+
450
+ # Default to json_facet if no other engine detected
451
+ 'json_facet'
452
+ end
453
+
454
+ def gem_present?(gem_name)
455
+ # Check if gem is in Gemfile
456
+ gemfile_path = File.join(destination_root, 'Gemfile')
457
+ return false unless File.exist?(gemfile_path)
458
+
459
+ File.read(gemfile_path).match?(/gem\s+['"]#{gem_name}['"]/)
460
+ rescue
461
+ false
462
+ end
481
463
  end
482
464
  end
@@ -0,0 +1,6 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ default from: "from@example.com"
3
+ layout "mailer"
4
+ end
5
+
6
+