propel_authentication 0.3.0 โ†’ 0.3.1.1

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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/lib/generators/propel_authentication/install_generator.rb +198 -241
  4. data/lib/generators/propel_authentication/templates/auth/passwords_controller.rb.tt +1 -4
  5. data/lib/generators/propel_authentication/templates/auth/signup_controller.rb.tt +3 -6
  6. data/lib/generators/propel_authentication/templates/auth/tokens_controller.rb.tt +2 -5
  7. data/lib/generators/propel_authentication/templates/core/configuration_methods.rb +38 -1
  8. data/lib/generators/propel_authentication/templates/db/migrate/create_agencies.rb +2 -0
  9. data/lib/generators/propel_authentication/templates/db/migrate/create_agents.rb +6 -1
  10. data/lib/generators/propel_authentication/templates/db/migrate/create_users.rb +2 -0
  11. data/lib/generators/propel_authentication/templates/db/propel_seeds.rb.tt +145 -0
  12. data/lib/generators/propel_authentication/templates/doc/signup_flow.md +9 -4
  13. data/lib/generators/propel_authentication/templates/fixtures/agencies.yml.erb +23 -0
  14. data/lib/generators/propel_authentication/templates/fixtures/agents.yml.erb +71 -0
  15. data/lib/generators/propel_authentication/templates/fixtures/invitations.yml.erb +9 -0
  16. data/lib/generators/propel_authentication/templates/fixtures/organizations.yml.erb +21 -0
  17. data/lib/generators/propel_authentication/templates/fixtures/users.yml.erb +77 -0
  18. data/lib/generators/propel_authentication/templates/models/agency.rb.tt +4 -0
  19. data/lib/generators/propel_authentication/templates/models/agent.rb.tt +9 -0
  20. data/lib/generators/propel_authentication/templates/models/invitation.rb.tt +3 -1
  21. data/lib/generators/propel_authentication/templates/models/organization.rb.tt +3 -0
  22. data/lib/generators/propel_authentication/templates/propel_authentication.rb.tt +33 -6
  23. data/lib/generators/propel_authentication/templates/test/controllers/auth/lockable_integration_test.rb.tt +1 -1
  24. data/lib/generators/propel_authentication/templates/test/controllers/auth/password_reset_integration_test.rb.tt +1 -1
  25. data/lib/generators/propel_authentication/templates/test/controllers/auth/tokens_controller_test.rb.tt +4 -4
  26. data/lib/propel_authentication.rb +1 -1
  27. metadata +8 -3
  28. data/lib/generators/propel_authentication/templates/db/seeds.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: feff8cf5d61966deceb32c0466338c47270c96b06d67304aeeab26304402f83f
4
- data.tar.gz: 9a5d2b1e807454d4223524dad81b109dd97a655a7ce0512a49c8d22c65c9ddff
3
+ metadata.gz: ab07de559d01cd814a50a27f9efa81400322e72c124eb7d23ff0ef5c7b815e49
4
+ data.tar.gz: 5f2192a1383654c5a871f1377d8e70a9622a8fbf27769dc5cc29b63f14250092
5
5
  SHA512:
6
- metadata.gz: 18219d594b8084f6dc283d2e5d034413f69492c3ca9861588c40170659586150f118acf23bc9003356144704a4648c84b8265dafbd81e9bad8fc722779b4fd93
7
- data.tar.gz: 2bcf4ca9a1779fb6487d9e31e28e5035cc71771e1f7983501b1697fd94b78441f849776e76dc73f4c895d84ac739e2bc91c6b0624a06d1ea9b163e4b02c653e2
6
+ metadata.gz: 95ed0ee1e549419f6b2aeca658a8ca1fd1bc30472280115a2ff25e9d9a983df3da3c1d408e29138d059880320416c212528e7f89eaa1158e7a590f28b3837ce9
7
+ data.tar.gz: bf476f4b9eb72e859feb34adb3bb12d28ec1b21b156e7764e410af7dc3f5f78fd635e24e61d6f5e9d3ee6fec4a71edde59c275dabf34fdeb925f919ef056c531
data/CHANGELOG.md CHANGED
@@ -13,6 +13,63 @@ 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.3.1.1] - 2025-09-11
17
+
18
+ ### ๐Ÿ› Bug Fixes
19
+ - **PostgreSQL Migration Compatibility**: Fixed migration generation issues affecting PostgreSQL databases
20
+ - Enhanced migration templates for agencies, agents, organizations, and users to work correctly with PostgreSQL
21
+ - Fixed foreign key constraint generation for PostgreSQL compatibility
22
+ - Corrected multi-tenant migration templates for better PostgreSQL support
23
+
24
+ ## [0.3.1] - 2025-09-11
25
+
26
+ ### ๐Ÿ”ง Installation & Configuration Improvements
27
+ - **Enhanced Install Generator**: Improved handling of noticed gem installation and environment configuration errors
28
+ - Better error detection and handling for missing environment variables
29
+ - Enhanced installation process for the noticed gem integration
30
+ - More robust handling of gem installation edge cases
31
+ - **Fixed duplicate gem insert bug**: Generator now properly checks for existing gem entries before insertion
32
+ - **Improved Seed File Generation**: Enhanced PropelSeeds template with better organization and agent relationships
33
+ - Better seed data structure for multi-tenant scenarios
34
+ - Enhanced fixture and seed file coordination
35
+ - Fixed seed file imports to reflect proper organization tenancy structure
36
+ - **Enhanced Tenancy Configuration System**: Comprehensive improvements to configuration methods and templates
37
+ - Enhanced `PropelAuthentication.configuration` with better tenancy model support
38
+ - Improved configuration methods in core authentication system
39
+ - Better migration templates for agencies, agents, organizations, and users
40
+ - Enhanced model templates with improved association handling
41
+
42
+ ### ๐Ÿ—๏ธ Relationship Model Enhancements
43
+ - **Direct Agent-Organization Relationship**: Added direct relationship between Agent and Organization models
44
+ - Enhanced agency and organization model templates with improved associations
45
+ - Better support for multi-tenant organizational structures
46
+ - Improved migration templates to support direct agent-organization relationships
47
+ - **Enhanced User Model Relationships**: Improved user model template with better agency and organization associations
48
+ - Enhanced model relationships for cleaner multi-tenant access patterns
49
+ - Better integration with PropelApi polymorphic support
50
+
51
+ ### ๐Ÿงช Testing & Fixtures Improvements
52
+ - **Enhanced Fixture Templates**: Improved fixture generation with ERB templates for agencies, agents, organizations, users, and invitations
53
+ - Better fixture data coordination across authentication models
54
+ - Enhanced test setup with realistic fixture relationships
55
+ - Improved fixture template adoption for better integration with PropelApi generators
56
+ - **Test Template Updates**: Enhanced authentication test templates for better integration
57
+ - Improved lockable integration test templates
58
+ - Enhanced password reset integration test templates
59
+ - Better token controller test templates with improved authentication flows
60
+
61
+ ### ๐Ÿ› ๏ธ Generator & Template System
62
+ - **Controller Template Enhancements**: Comprehensive improvements to authentication controller templates
63
+ - Enhanced signup controller template with better organization and agency handling
64
+ - Improved passwords controller template for better error handling
65
+ - Updated tokens controller template with enhanced authentication flows
66
+ - Better integration with full-stack and API-only Rails application architectures
67
+ - **Configuration Method Improvements**: Enhanced core configuration methods for better tenancy support
68
+ - **Migration Template Improvements**: Enhanced migration templates for agencies, agents, and users with better relationship support
69
+ - Improved create_agencies migration template
70
+ - Enhanced create_agents migration with better relationship handling
71
+ - Updated create_users migration for improved multi-tenancy support
72
+
16
73
  ## [0.3.0] - 2025-01-15
17
74
 
18
75
  ### ๐Ÿ”ง Compatibility Updates
@@ -33,6 +33,30 @@ module PropelAuthentication
33
33
 
34
34
  desc "Generate JWT-based authentication system with configurable URL architecture"
35
35
 
36
+ class_option :namespace,
37
+ type: :string,
38
+ desc: "API namespace (e.g., api)"
39
+
40
+ class_option :version,
41
+ type: :string,
42
+ desc: "API version (e.g., v1)"
43
+
44
+ class_option :auth_scope,
45
+ type: :string,
46
+ desc: "Authentication scope (e.g., auth for /api/v1/auth/login)"
47
+
48
+ class_option :tenancy_enabled,
49
+ type: :boolean,
50
+ desc: "Enable multi-tenancy system (master switch)"
51
+
52
+ class_option :organization_required,
53
+ type: :boolean,
54
+ desc: "Require users to belong to organizations"
55
+
56
+ class_option :agency_required,
57
+ type: :boolean,
58
+ desc: "Enable agency tenancy within organizations"
59
+
36
60
  def copy_jwt_initializer
37
61
  determine_configuration
38
62
 
@@ -43,18 +67,25 @@ module PropelAuthentication
43
67
  # Convert to ERB template to support configuration
44
68
  template "propel_authentication.rb.tt", "config/initializers/propel_authentication.rb"
45
69
  say "Created PropelAuthentication configuration with namespace: #{namespace_display}, version: #{version_display}", :green
70
+
71
+ # Load the configuration immediately so templates can access it
72
+ load_propel_authentication_configuration
46
73
  end
47
74
  end
48
75
 
49
76
  def copy_authentication_models
50
77
  # Detect rendering engine for conditional facet generation
51
78
  @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"
79
+ # Organizations must be created first if required (users depend on organizations)
80
+ copy_organizations_model if organization_required?
81
+ # Agencies must be created before agents and users (if agency auth is enabled)
82
+ copy_agencies_model if agency_required?
83
+ # Users can now be created (organizations and agencies exist)
84
+ copy_users_model
85
+ # Agents depend on users and agencies
86
+ copy_agents_model if agency_required?
87
+ # Invitations depend on users and organizations
88
+ copy_invitations_model
58
89
  end
59
90
 
60
91
  def copy_authentication_concerns
@@ -106,18 +137,37 @@ module PropelAuthentication
106
137
  template "test/controllers/auth/password_reset_integration_test.rb.tt", "test/controllers/auth/password_reset_integration_test.rb"
107
138
  end
108
139
 
109
- def copy_test_fixtures
110
- create_file "test/fixtures/organizations.yml", organizations_fixture
111
- create_file "test/fixtures/users.yml", users_fixture
112
- create_file "test/fixtures/agencies.yml", agencies_fixture
113
- create_file "test/fixtures/agents.yml", agents_fixture
114
- create_file "test/fixtures/invitations.yml", invitations_fixture
115
- end
116
140
 
117
141
  def add_authentication_gems
118
142
  add_gem_if_missing('bcrypt', '~> 3.1.20')
119
143
  add_gem_if_missing('jwt', '~> 3.1.2')
144
+ add_gem_if_missing('noticed', '~> 2.8.1')
120
145
  add_gem_if_missing('letter_opener', '~> 1.10', group: :development)
146
+
147
+ say "๐Ÿ“ฆ Installing gems...", :blue
148
+ run "bundle install"
149
+
150
+ # Require bcrypt so it's available for fixture templates
151
+ begin
152
+ require 'bcrypt'
153
+ rescue LoadError
154
+ say "โš ๏ธ BCrypt not yet available, fixtures may need manual adjustment", :yellow
155
+ end
156
+ end
157
+
158
+ def install_noticed_gem
159
+ say ""
160
+ say "๐Ÿ“ฆ Setting up Noticed gem for email notifications...", :green
161
+
162
+ begin
163
+ # Run the noticed install generator
164
+ rails_command "noticed:install:migrations", capture: true
165
+ say "โœ… Noticed gem configured successfully", :green
166
+ rescue => e
167
+ say "โš ๏ธ Warning: Could not run noticed:install:migrations automatically", :yellow
168
+ say " Please run manually: rails generate noticed:install", :yellow
169
+ say " Error: #{e.message}", :red if options[:verbose]
170
+ end
121
171
  end
122
172
 
123
173
  def add_authentication_routes
@@ -136,16 +186,30 @@ module PropelAuthentication
136
186
  route template_file_for_routes
137
187
  end
138
188
 
139
- def copy_authentication_migrations
140
- %w[organizations users agencies agents invitations].each do |table|
141
- unless migration_exists?("create_#{table}")
142
- migration_template "db/migrate/create_#{table}.rb", "db/migrate/create_#{table}.rb"
143
- end
144
- end
189
+ def copy_authentication_migrations_and_fixtures
190
+ # Organizations must be created first if required (users depend on organizations)
191
+ copy_organizations_migration_and_fixtures if organization_required?
192
+ # Agencies must be created before agents and users (if agency auth is enabled)
193
+ copy_agencies_migration_and_fixtures if agency_required?
194
+ # Users can now be created (organizations and agencies exist)
195
+ copy_users_migration_and_fixtures
196
+ # Agents depend on users and agencies
197
+ copy_agents_migration_and_fixtures if agency_required?
198
+ # Invitations depend on users and organizations
199
+ copy_invitations_migration_and_fixtures
145
200
  end
146
201
 
147
202
  def copy_database_seeds
148
- copy_file "db/seeds.rb", "db/seeds.rb"
203
+ template "db/propel_seeds.rb.tt", "db/propel_seeds.rb"
204
+
205
+ # Add require_relative to main seeds.rb file so propel_seeds is loaded during rails db:seed
206
+ seeds_file = File.join(destination_root, "db/seeds.rb")
207
+ if File.exist?(seeds_file)
208
+ seeds_content = File.read(seeds_file)
209
+ unless seeds_content.include?("require_relative 'propel_seeds'")
210
+ append_to_file "db/seeds.rb", "\n# Load Propel Authentication seed data\nrequire_relative 'propel_seeds'\n"
211
+ end
212
+ end
149
213
  end
150
214
 
151
215
  def extract_generator_for_customization
@@ -197,6 +261,18 @@ module PropelAuthentication
197
261
 
198
262
  private
199
263
 
264
+ def load_propel_authentication_configuration
265
+ # Load the configuration file we just created so templates can access it
266
+ config_file = File.join(destination_root, "config/initializers/propel_authentication.rb")
267
+ if File.exist?(config_file)
268
+ begin
269
+ load config_file
270
+ rescue => e
271
+ say "Warning: Could not load PropelAuthentication configuration: #{e.message}", :yellow
272
+ end
273
+ end
274
+ end
275
+
200
276
  # Check if authentication routes already exist in routes file
201
277
  def authentication_routes_exist?(routes_content)
202
278
  # Check for key authentication routes based on our configuration
@@ -227,232 +303,11 @@ module PropelAuthentication
227
303
  ERB.new(File.read(source_path), trim_mode: '-').result(binding)
228
304
  end
229
305
 
230
- def add_gem_if_missing(gem_name, version_requirement = nil, options = {})
231
- gemfile_path = File.join(destination_root, 'Gemfile')
232
- return unless File.exist?(gemfile_path)
233
-
234
- gemfile_content = File.read(gemfile_path)
235
-
236
- # Check if gem is already present (handles various quote styles and spacing)
237
- gem_pattern = /gem\s+['"]#{Regexp.escape(gem_name)}['"](?:\s*,\s*['"][^'"]*['"])?/
238
-
239
- if gemfile_content.match?(gem_pattern)
240
- say_status :exists, "gem '#{gem_name}' already in Gemfile", :blue
241
- return
242
- end
243
-
244
- # Add the gem using Rails' built-in method
245
- if version_requirement && options.any?
246
- gem gem_name, version_requirement, options
247
- elsif version_requirement
248
- gem gem_name, version_requirement
249
- else
250
- gem gem_name
251
- end
252
-
253
- say_status :gemfile, "gem '#{gem_name}' #{version_requirement}", :green
254
- end
255
306
 
256
307
  def migration_exists?(migration_name)
257
308
  Dir.glob("#{destination_root}/db/migrate/*_#{migration_name}.rb").any?
258
309
  end
259
310
 
260
- # Fixture content methods
261
- def organizations_fixture
262
- <<~FIXTURE
263
- acme_org:
264
- name: "Acme Corporation"
265
- website: "https://acme-corp.com"
266
- time_zone: "UTC"
267
- logo: "https://acme-corp.com/logo.png"
268
- slug: "acme-corporation"
269
- metadata: { org_type: "enterprise", industry: "technology", size: "large" }
270
- settings: { theme: "corporate", timezone: "EST", features: "premium" }
271
- created_at: <%= 30.days.ago %>
272
- updated_at: <%= 1.day.ago %>
273
-
274
- tech_startup:
275
- name: "Tech Startup Inc"
276
- website: "https://techstartup.io"
277
- time_zone: "America/New_York"
278
- logo: "https://techstartup.io/logo.png"
279
- slug: "tech-startup-inc"
280
- metadata: { org_type: "startup", industry: "software", size: "small" }
281
- settings: { theme: "modern", timezone: "PST", features: "basic" }
282
- created_at: <%= 15.days.ago %>
283
- updated_at: <%= 2.days.ago %>
284
- FIXTURE
285
- end
286
-
287
- def users_fixture
288
- <<~FIXTURE
289
- john_user:
290
- email_address: "john@example.com"
291
- username: "john_doe"
292
- first_name: "John"
293
- last_name: "Doe"
294
- password_digest: "<%= BCrypt::Password.create('password123') %>"
295
- organization: acme_org
296
- status: "active"
297
- confirmed_at: null
298
- confirmation_token: "<%= SecureRandom.hex(32) %>"
299
- confirmation_sent_at: <%= 1.hour.ago %>
300
- metadata: { user_type: "admin", department: "engineering", priority: "high" }
301
- settings: { theme: "dark", language: "en", notifications: true }
302
- created_at: <%= 7.days.ago %>
303
- updated_at: <%= 1.day.ago %>
304
-
305
- jane_user:
306
- email_address: "jane@example.com"
307
- username: "jane_smith"
308
- first_name: "Jane"
309
- last_name: "Smith"
310
- password_digest: "<%= BCrypt::Password.create('password123') %>"
311
- organization: tech_startup
312
- status: "active"
313
- confirmed_at: null
314
- failed_login_attempts: 0
315
- locked_at: null
316
- metadata: { user_type: "manager", department: "marketing", priority: "high" }
317
- settings: { theme: "light", language: "en", notifications: false }
318
- created_at: <%= 5.days.ago %>
319
- updated_at: <%= 1.day.ago %>
320
-
321
- confirmed_user:
322
- email_address: "confirmed@example.com"
323
- username: "confirmed_user"
324
- first_name: "Confirmed"
325
- last_name: "User"
326
- password_digest: "<%= BCrypt::Password.create('password123') %>"
327
- organization: acme_org
328
- status: "active"
329
- confirmed_at: <%= 7.days.ago %>
330
- metadata: { user_type: "employee", department: "sales", priority: "medium" }
331
- settings: { theme: "auto", language: "es", notifications: true }
332
- created_at: <%= 14.days.ago %>
333
- updated_at: <%= 1.day.ago %>
334
-
335
- locked_user:
336
- email_address: "locked@example.com"
337
- username: "locked_user"
338
- first_name: "Locked"
339
- last_name: "User"
340
- password_digest: "<%= BCrypt::Password.create('password123') %>"
341
- organization: acme_org
342
- status: "active"
343
- confirmed_at: <%= 10.days.ago %>
344
- failed_login_attempts: 5
345
- locked_at: <%= 1.hour.ago %>
346
- metadata: { user_type: "employee", department: "support", priority: "low" }
347
- settings: { theme: "light", language: "en", notifications: false }
348
- created_at: <%= 20.days.ago %>
349
- updated_at: <%= 1.hour.ago %>
350
-
351
- expired_confirmation_user:
352
- email_address: "expired@example.com"
353
- username: "expired_user"
354
- first_name: "Expired"
355
- last_name: "User"
356
- password_digest: "<%= BCrypt::Password.create('password123') %>"
357
- organization: tech_startup
358
- status: "active"
359
- confirmed_at: null
360
- confirmation_token: "<%= SecureRandom.hex(32) %>"
361
- confirmation_sent_at: <%= 25.hours.ago %>
362
- metadata: { user_type: "test", department: "qa", priority: "low" }
363
- settings: { theme: "dark", language: "fr", notifications: false }
364
- created_at: <%= 30.days.ago %>
365
- updated_at: <%= 25.hours.ago %>
366
- FIXTURE
367
- end
368
-
369
- def agencies_fixture
370
- <<~FIXTURE
371
- marketing_agency:
372
- name: "Marketing Solutions"
373
- organization: acme_org
374
- created_at: <%= 10.days.ago %>
375
- updated_at: <%= 2.days.ago %>
376
-
377
- sales_agency:
378
- name: "Sales Department"
379
- organization: acme_org
380
- created_at: <%= 9.days.ago %>
381
- updated_at: <%= 2.days.ago %>
382
-
383
- tech_agency:
384
- name: "Tech Solutions"
385
- organization: tech_startup
386
- created_at: <%= 8.days.ago %>
387
- updated_at: <%= 1.day.ago %>
388
-
389
- support_agency:
390
- name: "Support Team"
391
- organization: tech_startup
392
- created_at: <%= 7.days.ago %>
393
- updated_at: <%= 1.day.ago %>
394
- FIXTURE
395
- end
396
-
397
- def agents_fixture
398
- <<~FIXTURE
399
- john_marketing_agent:
400
- user: john_user
401
- agency: marketing_agency
402
- role: "manager"
403
- created_at: <%= 8.days.ago %>
404
- updated_at: <%= 1.day.ago %>
405
-
406
- confirmed_sales_agent:
407
- user: confirmed_user
408
- agency: sales_agency
409
- role: "analyst"
410
- created_at: <%= 7.days.ago %>
411
- updated_at: <%= 1.day.ago %>
412
-
413
- locked_marketing_agent:
414
- user: locked_user
415
- agency: marketing_agency
416
- role: "coordinator"
417
- created_at: <%= 6.days.ago %>
418
- updated_at: <%= 1.day.ago %>
419
-
420
- jane_tech_agent:
421
- user: jane_user
422
- agency: tech_agency
423
- role: "developer"
424
- created_at: <%= 5.days.ago %>
425
- updated_at: <%= 1.day.ago %>
426
-
427
- expired_support_agent:
428
- user: expired_confirmation_user
429
- agency: support_agency
430
- role: "specialist"
431
- created_at: <%= 4.days.ago %>
432
- updated_at: <%= 1.day.ago %>
433
-
434
- locked_sales_agent:
435
- user: locked_user
436
- agency: sales_agency
437
- role: "trainee"
438
- created_at: <%= 3.days.ago %>
439
- updated_at: <%= 1.day.ago %>
440
- FIXTURE
441
- end
442
-
443
- def invitations_fixture
444
- <<~FIXTURE
445
- pending_invitation:
446
- email_address: "newuser@example.com"
447
- first_name: "New"
448
- last_name: "User"
449
- organization: acme_org
450
- inviter: john_user
451
- status: "pending"
452
- created_at: <%= 3.days.ago %>
453
- updated_at: <%= 3.days.ago %>
454
- FIXTURE
455
- end
456
311
 
457
312
  def detect_rendering_engine
458
313
  # Check for common rendering engines in order of preference
@@ -474,5 +329,107 @@ module PropelAuthentication
474
329
  rescue
475
330
  false
476
331
  end
332
+
333
+ private
334
+
335
+ # Individual model methods
336
+ def copy_users_model
337
+ template "models/user.rb.tt", "app/models/user.rb"
338
+ end
339
+
340
+ def copy_organizations_model
341
+ template "models/organization.rb.tt", "app/models/organization.rb"
342
+ end
343
+
344
+ def copy_agencies_model
345
+ template "models/agency.rb.tt", "app/models/agency.rb"
346
+ end
347
+
348
+ def copy_agents_model
349
+ template "models/agent.rb.tt", "app/models/agent.rb"
350
+ end
351
+
352
+ def copy_invitations_model
353
+ template "models/invitation.rb.tt", "app/models/invitation.rb"
354
+ end
355
+
356
+ # Combined migration and fixture methods
357
+ def copy_users_migration_and_fixtures
358
+ migration_template "db/migrate/create_users.rb", "db/migrate/create_users.rb" unless migration_exists?("create_users")
359
+ template "fixtures/users.yml.erb", "test/fixtures/users.yml"
360
+ end
361
+
362
+ def copy_organizations_migration_and_fixtures
363
+ migration_template "db/migrate/create_organizations.rb", "db/migrate/create_organizations.rb" unless migration_exists?("create_organizations")
364
+ template "fixtures/organizations.yml.erb", "test/fixtures/organizations.yml"
365
+ end
366
+
367
+ def copy_agencies_migration_and_fixtures
368
+ migration_template "db/migrate/create_agencies.rb", "db/migrate/create_agencies.rb" unless migration_exists?("create_agencies")
369
+ template "fixtures/agencies.yml.erb", "test/fixtures/agencies.yml"
370
+ end
371
+
372
+ def copy_agents_migration_and_fixtures
373
+ migration_template "db/migrate/create_agents.rb", "db/migrate/create_agents.rb" unless migration_exists?("create_agents")
374
+ template "fixtures/agents.yml.erb", "test/fixtures/agents.yml"
375
+ end
376
+
377
+ def copy_invitations_migration_and_fixtures
378
+ migration_template "db/migrate/create_invitations.rb", "db/migrate/create_invitations.rb" unless migration_exists?("create_invitations")
379
+ template "fixtures/invitations.yml.erb", "test/fixtures/invitations.yml"
380
+ end
381
+
382
+ # Configuration helper methods
383
+ def organization_required?
384
+ return true unless configuration_loaded?
385
+ PropelAuthentication.configuration.organization_required?
386
+ rescue
387
+ true # Default to full tenancy if config unavailable
388
+ end
389
+
390
+ def agency_required?
391
+ return true unless configuration_loaded?
392
+ PropelAuthentication.configuration.agency_required?
393
+ rescue
394
+ true # Default to full tenancy if config unavailable
395
+ end
396
+
397
+ def configuration_loaded?
398
+ defined?(PropelAuthentication) &&
399
+ PropelAuthentication.respond_to?(:configuration) &&
400
+ PropelAuthentication.configuration.present?
401
+ rescue
402
+ false
403
+ end
404
+
405
+ def add_gem_if_missing(gem_name, version_requirement = nil, options = {})
406
+ gemfile_path = File.join(destination_root, 'Gemfile')
407
+ return unless File.exist?(gemfile_path)
408
+
409
+ gemfile_content = File.read(gemfile_path)
410
+
411
+ # Check if gem is already present and not commented out
412
+ gem_pattern = /^\s*gem\s+['"]#{Regexp.escape(gem_name)}['"](?:\s*,\s*['"][^'"]*['"])?/
413
+ commented_gem_pattern = /^\s*#.*gem\s+['"]#{Regexp.escape(gem_name)}['"]/
414
+
415
+ # Check each line to see if the gem exists and is not commented out
416
+ gem_exists = gemfile_content.lines.any? do |line|
417
+ line.match?(gem_pattern) && !line.match?(commented_gem_pattern)
418
+ end
419
+
420
+ if gem_exists
421
+ say_status :exists, "gem '#{gem_name}' already in Gemfile", :blue
422
+ return
423
+ end
424
+
425
+ # Use Rails built-in gem method to add it
426
+ if options[:group]
427
+ gem gem_name, version_requirement, group: options[:group]
428
+ else
429
+ gem gem_name, version_requirement
430
+ end
431
+
432
+ say_status :gemfile, "gem '#{gem_name}' #{version_requirement}", :green
433
+ end
477
434
  end
478
435
  end
@@ -1,7 +1,4 @@
1
- class <%= auth_controller_class_name('passwords') %> < ApplicationController
2
- <%- unless api_only_app? -%>
3
- include RackSessionDisable
4
- <%- end -%>
1
+ class <%= auth_controller_class_name('passwords') %> < Api::BaseController
5
2
  include PropelAuthenticationConcern
6
3
 
7
4
  # POST <%= auth_route_prefix %>/reset
@@ -1,8 +1,4 @@
1
- class <%= auth_controller_class_name('signup') %> < ApplicationController
2
- <%- unless api_only_app? -%>
3
- include RackSessionDisable
4
- <%- end -%>
5
-
1
+ class <%= auth_controller_class_name('signup') %> < Api::BaseController
6
2
  # POST <%= auth_route_prefix %>/signup
7
3
  def create
8
4
  # Validate agency requirements if agency tenancy is enabled
@@ -19,6 +15,7 @@ class <%= auth_controller_class_name('signup') %> < ApplicationController
19
15
  # Create agent relationship so user has immediate agency access
20
16
  @user.agents.create!(
21
17
  agency: @agency,
18
+ organization: @organization,
22
19
  role: agent_role_param
23
20
  )
24
21
  end
@@ -187,7 +184,7 @@ class <%= auth_controller_class_name('signup') %> < ApplicationController
187
184
  def agency_tenancy_enabled?
188
185
  # Check PropelAuthentication configuration (owns tenancy models)
189
186
  if defined?(PropelAuthentication) && PropelAuthentication.respond_to?(:configuration)
190
- PropelAuthentication.configuration.agency_tenancy
187
+ PropelAuthentication.configuration.agency_required?
191
188
  else
192
189
  true # Safe default - enables agency tenancy when configuration unavailable
193
190
  end
@@ -1,7 +1,4 @@
1
- class <%= auth_controller_class_name('tokens') %> < ApplicationController
2
- <%- unless api_only_app? -%>
3
- include RackSessionDisable
4
- <%- end -%>
1
+ class <%= auth_controller_class_name('tokens') %> < Api::BaseController
5
2
  include PropelAuthenticationConcern
6
3
 
7
4
  before_action :authenticate_user, only: [:show, :refresh]
@@ -42,7 +39,7 @@ class <%= auth_controller_class_name('tokens') %> < ApplicationController
42
39
  render json: { error: 'Invalid credentials' }, status: :unauthorized
43
40
  end
44
41
  rescue ActionController::ParameterMissing
45
- render json: { error: 'Missing required parameters' }, status: :unprocessable_content
42
+ render json: { error: 'Missing required parameters' }, status: :bad_request
46
43
  end
47
44
 
48
45
  # DELETE <%= auth_route_prefix %>/logout