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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -0
- data/lib/generators/propel_authentication/install_generator.rb +198 -241
- data/lib/generators/propel_authentication/templates/auth/passwords_controller.rb.tt +1 -4
- data/lib/generators/propel_authentication/templates/auth/signup_controller.rb.tt +3 -6
- data/lib/generators/propel_authentication/templates/auth/tokens_controller.rb.tt +2 -5
- data/lib/generators/propel_authentication/templates/core/configuration_methods.rb +38 -1
- data/lib/generators/propel_authentication/templates/db/migrate/create_agencies.rb +2 -0
- data/lib/generators/propel_authentication/templates/db/migrate/create_agents.rb +6 -1
- data/lib/generators/propel_authentication/templates/db/migrate/create_users.rb +2 -0
- data/lib/generators/propel_authentication/templates/db/propel_seeds.rb.tt +145 -0
- data/lib/generators/propel_authentication/templates/doc/signup_flow.md +9 -4
- data/lib/generators/propel_authentication/templates/fixtures/agencies.yml.erb +23 -0
- data/lib/generators/propel_authentication/templates/fixtures/agents.yml.erb +71 -0
- data/lib/generators/propel_authentication/templates/fixtures/invitations.yml.erb +9 -0
- data/lib/generators/propel_authentication/templates/fixtures/organizations.yml.erb +21 -0
- data/lib/generators/propel_authentication/templates/fixtures/users.yml.erb +77 -0
- data/lib/generators/propel_authentication/templates/models/agency.rb.tt +4 -0
- data/lib/generators/propel_authentication/templates/models/agent.rb.tt +9 -0
- data/lib/generators/propel_authentication/templates/models/invitation.rb.tt +3 -1
- data/lib/generators/propel_authentication/templates/models/organization.rb.tt +3 -0
- data/lib/generators/propel_authentication/templates/propel_authentication.rb.tt +33 -6
- data/lib/generators/propel_authentication/templates/test/controllers/auth/lockable_integration_test.rb.tt +1 -1
- data/lib/generators/propel_authentication/templates/test/controllers/auth/password_reset_integration_test.rb.tt +1 -1
- data/lib/generators/propel_authentication/templates/test/controllers/auth/tokens_controller_test.rb.tt +4 -4
- data/lib/propel_authentication.rb +1 -1
- metadata +8 -3
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab07de559d01cd814a50a27f9efa81400322e72c124eb7d23ff0ef5c7b815e49
|
4
|
+
data.tar.gz: 5f2192a1383654c5a871f1377d8e70a9622a8fbf27769dc5cc29b63f14250092
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
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') %> <
|
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') %> <
|
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.
|
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') %> <
|
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: :
|
42
|
+
render json: { error: 'Missing required parameters' }, status: :bad_request
|
46
43
|
end
|
47
44
|
|
48
45
|
# DELETE <%= auth_route_prefix %>/logout
|