Class: Organizations::Configuration
- Inherits:
-
Object
- Object
- Organizations::Configuration
- Defined in:
- lib/organizations/configuration.rb
Overview
Configuration class for the Organizations gem. Provides all customization options for organization behavior.
Constant Summary collapse
- ENGINE_ROUTE_GROUPS =
%i[switching organizations memberships invitations public_invitations].freeze
Instance Attribute Summary collapse
-
#additional_organization_params ⇒ Object
Organizations Controller === Additional params to permit when creating/updating organizations.
-
#after_organization_created_redirect_path ⇒ Object
Where to redirect after organization is created (nil = default show page) Can be a String ("/dashboard") or Proc (->(org) { "/orgs/#orgorg.id" }).
-
#always_create_personal_organization_for_each_user ⇒ Object
Auto-creation ===.
-
#always_require_users_to_belong_to_one_organization ⇒ Object
Onboarding === Require users to always belong to at least one organization Set to true to prevent users from leaving their last organization.
-
#authenticate_user_method ⇒ Object
Method that ensures user is authenticated (default: :authenticate_user!).
-
#authenticated_controller_layout ⇒ Object
Layout for authenticated engine controllers (OrganizationsController, etc.) Can be nil (use controller default), String, or Symbol.
-
#current_user_method ⇒ Object
Method that returns the current user (default: :current_user).
-
#custom_roles_definition ⇒ Object
readonly
Custom Roles ===.
-
#default_invitation_role ⇒ Object
Default role for invited members.
-
#default_organization_name ⇒ Object
Name for auto-created organizations (only used when always_create_personal_organization_for_each_user = true) Can be a String or a Proc/Lambda: ->(user) { "#useruser.name's Workspace" }.
-
#engine_routes ⇒ Object
Which engine route groups to draw (devise_for-style skip/only, see https://rubydoc.info/github/heartcombo/devise/main/ActionDispatch/Routing/Mapper#devise_for-instance_method for the pattern precedent).
-
#invitation_expiry ⇒ Object
Invitations === How long invitations are valid.
-
#invitation_mailer ⇒ Object
Custom mailer for invitations (class name as string).
-
#join_code_generator ⇒ Object
Custom join code generator.
-
#join_request_expiry ⇒ Object
How long join requests stay pending before they read as expired (derived status, like invitations).
-
#max_organizations_per_user ⇒ Object
Limits === Maximum organizations a user can own (nil = unlimited).
-
#no_organization_alert ⇒ Object
Default flash alert for no-organization redirects when using the built-in handler nil keeps backward-compatible default alert.
-
#no_organization_handler ⇒ Object
readonly
Handlers (blocks) ===.
-
#no_organization_notice ⇒ Object
Default flash notice for no-organization redirects when using the built-in handler nil means no notice.
-
#on_join_request_approved_callback ⇒ Object
readonly
Callbacks ===.
-
#on_join_request_created_callback ⇒ Object
readonly
Callbacks ===.
-
#on_join_request_rejected_callback ⇒ Object
readonly
Callbacks ===.
-
#on_member_invited_callback ⇒ Object
readonly
Callbacks ===.
-
#on_member_joined_callback ⇒ Object
readonly
Callbacks ===.
-
#on_member_joining_callback ⇒ Object
readonly
Callbacks ===.
-
#on_member_removed_callback ⇒ Object
readonly
Callbacks ===.
-
#on_organization_created_callback ⇒ Object
readonly
Callbacks ===.
-
#on_ownership_transferred_callback ⇒ Object
readonly
Callbacks ===.
-
#on_role_changed_callback ⇒ Object
readonly
Callbacks ===.
-
#on_verification_delivery_failed_callback ⇒ Object
readonly
Callbacks ===.
-
#parent_controller ⇒ Object
Base controller for authenticated routes (default: ::ApplicationController).
-
#public_controller ⇒ Object
Base controller for public routes like invitation acceptance (default: ActionController::Base) Use this to avoid inheriting host app filters that enforce authentication.
-
#public_controller_helpers ⇒ Object
Host helper modules to mix into the PUBLIC engine controller — it inherits ActionController::Base (not the host ApplicationController), so host layouts rendered by public pages need their helper modules declared here.
-
#public_controller_layout ⇒ Object
Layout for public engine controllers (PublicInvitationsController, etc.) Can be nil (use controller default), String, or Symbol.
-
#redirect_path_after_invitation_accepted ⇒ Object
Where to redirect after invitation is accepted Can be nil (use default: root_path), a String ("/dashboard"), or a Proc receiving (invitation, user).
-
#redirect_path_after_organization_switched ⇒ Object
Where to redirect after organization switch Can be nil (use default: root_path), a String ("/dashboard"), or a Proc receiving (organization, user).
-
#redirect_path_when_invitation_requires_authentication ⇒ Object
Invitation Flow Redirects === Where to redirect unauthenticated users when they try to accept an invitation Can be nil (use default: new_user_registration_path or root_path), a String ("/users/sign_up"), or a Proc receiving (invitation, user).
-
#redirect_path_when_no_organization ⇒ Object
Redirects === Where to redirect when user has no organization.
-
#session_key ⇒ Object
Session/Switching === Session key for storing current organization ID.
-
#trust_confirmed_account_email ⇒ Object
Allow Organization#join_with_account_email! to trust a host user's already-confirmed account email (e.g. Devise :confirmable) as proof of inbox control, skipping the emailed code when the domain matches.
-
#unauthorized_handler ⇒ Object
readonly
Handlers (blocks) ===.
-
#user_class ⇒ Object
Authentication === Class name of the host's user model (default: "User").
-
#verification_code_ttl ⇒ Object
How long an emailed verification code stays valid.
-
#verification_email_normalizer ⇒ Object
Custom email normalizer for the verified_email uniqueness invariant.
-
#verification_mailer ⇒ Object
Verified Joining === Custom mailer for email-verification codes (class name as string).
-
#verification_max_attempts ⇒ Object
Maximum wrong-code attempts per challenge before it locks.
-
#verification_max_sends ⇒ Object
Maximum number of code sends per join request.
-
#verification_resend_interval ⇒ Object
Minimum time between (re)sends of a verification code for one request.
Instance Method Summary collapse
-
#engine_route_groups ⇒ Array<Symbol>
The resolved set of enabled groups.
-
#initialize ⇒ Configuration
constructor
A new instance of Configuration.
-
#normalize_verification_email(email) ⇒ String
Normalize an email through the configured (or default) normalizer.
-
#on_join_request_approved {|context| ... } ⇒ Object
Called when a join request is approved (manually or auto-approved).
-
#on_join_request_created {|context| ... } ⇒ Object
Called when a join request is created (request-to-join workflow).
-
#on_join_request_rejected {|context| ... } ⇒ Object
Called when a join request is rejected.
-
#on_member_invited {|context| ... } ⇒ Object
Called when a member is invited.
-
#on_member_joined {|context| ... } ⇒ Object
Called when a member joins (invitation accepted).
-
#on_member_joining {|context| ... } ⇒ Object
THE MEMBERSHIP GATE — called STRICTLY, inside the creating transaction, immediately BEFORE any non-owner membership row is inserted, on EVERY join path: add_member!, invitation acceptance, join-request approval (which covers join codes, domain-email verification, allowlists, and join_with_account_email!).
-
#on_member_removed {|context| ... } ⇒ Object
Called when a member is removed.
-
#on_no_organization {|context| ... } ⇒ Object
Configure no organization handler.
-
#on_organization_created {|context| ... } ⇒ Object
Called when an organization is created.
-
#on_ownership_transferred {|context| ... } ⇒ Object
Called when ownership is transferred.
-
#on_role_changed {|context| ... } ⇒ Object
Called when a member's role changes.
-
#on_unauthorized {|context| ... } ⇒ Object
Configure unauthorized access handler.
-
#on_verification_delivery_failed {|context| ... } ⇒ Object
Called when a verification-code email FAILS to enqueue/deliver.
-
#resolve_default_organization_name(user) ⇒ String
Resolve the default organization name for a user.
-
#roles { ... } ⇒ Object
Define custom roles with permissions.
-
#validate! ⇒ Object
Validate the configuration.
Constructor Details
#initialize ⇒ Configuration
Returns a new instance of Configuration.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/organizations/configuration.rb', line 263 def initialize # Authentication defaults @user_class = "User" @current_user_method = :current_user @authenticate_user_method = :authenticate_user! # Auto-creation defaults @always_create_personal_organization_for_each_user = false @default_organization_name = "Personal" # Invitation defaults @invitation_expiry = 7.days @default_invitation_role = :member @invitation_mailer = "Organizations::InvitationMailer" # Verified joining defaults @verification_mailer = "Organizations::VerificationMailer" @verification_code_ttl = 15.minutes @verification_max_attempts = 5 @verification_resend_interval = 60.seconds @verification_max_sends = 5 @verification_email_normalizer = nil @trust_confirmed_account_email = true @join_request_expiry = 30.days @join_code_generator = nil # Limits @max_organizations_per_user = nil # Onboarding @always_require_users_to_belong_to_one_organization = false # Session/switching @session_key = :current_organization_id # Redirects @redirect_path_when_no_organization = "/organizations/new" @after_organization_created_redirect_path = nil @no_organization_alert = nil @no_organization_notice = nil # Invitation flow redirects @redirect_path_when_invitation_requires_authentication = nil @redirect_path_after_invitation_accepted = nil @redirect_path_after_organization_switched = nil # Organizations controller @additional_organization_params = [] # Engine @engine_routes = nil @parent_controller = "::ApplicationController" @public_controller = "ActionController::Base" @authenticated_controller_layout = nil @public_controller_layout = nil @public_controller_helpers = [] # Handlers (nil by default - use default behavior) @unauthorized_handler = nil @no_organization_handler = nil # Callbacks (nil by default - no-op) @on_organization_created_callback = nil @on_member_invited_callback = nil @on_member_joining_callback = nil @on_member_joined_callback = nil @on_member_removed_callback = nil @on_role_changed_callback = nil @on_ownership_transferred_callback = nil @on_join_request_created_callback = nil @on_join_request_approved_callback = nil @on_join_request_rejected_callback = nil @on_verification_delivery_failed_callback = nil # Custom roles @custom_roles_definition = nil end |
Instance Attribute Details
#additional_organization_params ⇒ Object
Organizations Controller ===
Additional params to permit when creating/updating organizations
183 184 185 |
# File 'lib/organizations/configuration.rb', line 183 def additional_organization_params @additional_organization_params end |
#after_organization_created_redirect_path ⇒ Object
Where to redirect after organization is created (nil = default show page) Can be a String ("/dashboard") or Proc (->(org) { "/orgs/#Organizations::Configuration.orgorg.id" })
154 155 156 |
# File 'lib/organizations/configuration.rb', line 154 def after_organization_created_redirect_path @after_organization_created_redirect_path end |
#always_create_personal_organization_for_each_user ⇒ Object
Auto-creation ===
Create personal organization automatically on user signup.
This setting controls the user's first-time experience:
┌─────────────────────────────────────────────────────────────────────────┐ │ true → "Instant access" pattern │ │ │ │ User signs up → auto-created workspace → lands in app immediately │ │ │ │ Think: Notion, Slack, Trello │ │ "Sign up and start using it in seconds" │ │ │ │ Best for: productivity tools, note apps, simple SaaS │ └─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐ │ false → "Guided onboarding" pattern │ │ │ │ User signs up → onboarding wizard → enters company info → dashboard │ │ │ │ Think: Stripe, HubSpot, enterprise B2B tools │ │ "Tell us about your company before you start" │ │ │ │ Best for: B2B SaaS needing company details, billing info, etc. │ └─────────────────────────────────────────────────────────────────────────┘
Related settings:
- default_organization_name: Name for auto-created orgs (only when true)
- redirect_path_when_no_organization: Where to send users without an org
- always_require_users_to_belong_to_one_organization: Prevent leaving last org
84 85 86 |
# File 'lib/organizations/configuration.rb', line 84 def always_create_personal_organization_for_each_user @always_create_personal_organization_for_each_user end |
#always_require_users_to_belong_to_one_organization ⇒ Object
Onboarding ===
Require users to always belong to at least one organization Set to true to prevent users from leaving their last organization
142 143 144 |
# File 'lib/organizations/configuration.rb', line 142 def always_require_users_to_belong_to_one_organization @always_require_users_to_belong_to_one_organization end |
#authenticate_user_method ⇒ Object
Method that ensures user is authenticated (default: :authenticate_user!)
49 50 51 |
# File 'lib/organizations/configuration.rb', line 49 def authenticate_user_method @authenticate_user_method end |
#authenticated_controller_layout ⇒ Object
Layout for authenticated engine controllers (OrganizationsController, etc.) Can be nil (use controller default), String, or Symbol
227 228 229 |
# File 'lib/organizations/configuration.rb', line 227 def authenticated_controller_layout @authenticated_controller_layout end |
#current_user_method ⇒ Object
Method that returns the current user (default: :current_user)
46 47 48 |
# File 'lib/organizations/configuration.rb', line 46 def current_user_method @current_user_method end |
#custom_roles_definition ⇒ Object (readonly)
Custom Roles ===
261 262 263 |
# File 'lib/organizations/configuration.rb', line 261 def custom_roles_definition @custom_roles_definition end |
#default_invitation_role ⇒ Object
Default role for invited members
95 96 97 |
# File 'lib/organizations/configuration.rb', line 95 def default_invitation_role @default_invitation_role end |
#default_organization_name ⇒ Object
Name for auto-created organizations (only used when always_create_personal_organization_for_each_user = true) Can be a String or a Proc/Lambda: ->(user) { "#Organizations::Configuration.useruser.name's Workspace" }
88 89 90 |
# File 'lib/organizations/configuration.rb', line 88 def default_organization_name @default_organization_name end |
#engine_routes ⇒ Object
Which engine route groups to draw (devise_for-style skip/only, see https://rubydoc.info/github/heartcombo/devise/main/ActionDispatch/Routing/Mapper#devise_for-instance_method for the pattern precedent). nil (default) draws everything.
config.engine_routes = { except: [:organizations] } # no org CRUD
config.engine_routes = { only: [:switching, :public_invitations] }
Groups: :switching (POST /organizations/switch/:id), :organizations (org CRUD), :memberships, :invitations (authenticated management), :public_invitations (token acceptance pages).
Why this exists: hosts that keep the models but not the whole engine UI (e.g. an app where org creation is admin-vetted) previously had to SHADOW engine routes with redirects declared before the mount — a route-order-load-bearing hack that actually bit one production host (the engine's resources :organizations swallowed an app route as :id). Declare what you want instead.
204 205 206 |
# File 'lib/organizations/configuration.rb', line 204 def engine_routes @engine_routes end |
#invitation_expiry ⇒ Object
Invitations ===
How long invitations are valid
92 93 94 |
# File 'lib/organizations/configuration.rb', line 92 def invitation_expiry @invitation_expiry end |
#invitation_mailer ⇒ Object
Custom mailer for invitations (class name as string)
98 99 100 |
# File 'lib/organizations/configuration.rb', line 98 def invitation_mailer @invitation_mailer end |
#join_code_generator ⇒ Object
Custom join code generator. nil = built-in 8-char ambiguity-free code. Can be a Proc/Lambda: -> { ... } returning the code string.
133 134 135 |
# File 'lib/organizations/configuration.rb', line 133 def join_code_generator @join_code_generator end |
#join_request_expiry ⇒ Object
How long join requests stay pending before they read as expired (derived status, like invitations). nil = never expire.
129 130 131 |
# File 'lib/organizations/configuration.rb', line 129 def join_request_expiry @join_request_expiry end |
#max_organizations_per_user ⇒ Object
Limits ===
Maximum organizations a user can own (nil = unlimited)
137 138 139 |
# File 'lib/organizations/configuration.rb', line 137 def max_organizations_per_user @max_organizations_per_user end |
#no_organization_alert ⇒ Object
Default flash alert for no-organization redirects when using the built-in handler nil keeps backward-compatible default alert
158 159 160 |
# File 'lib/organizations/configuration.rb', line 158 def no_organization_alert @no_organization_alert end |
#no_organization_handler ⇒ Object (readonly)
Handlers (blocks) ===
243 244 245 |
# File 'lib/organizations/configuration.rb', line 243 def no_organization_handler @no_organization_handler end |
#no_organization_notice ⇒ Object
Default flash notice for no-organization redirects when using the built-in handler nil means no notice
162 163 164 |
# File 'lib/organizations/configuration.rb', line 162 def no_organization_notice @no_organization_notice end |
#on_join_request_approved_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_join_request_approved_callback @on_join_request_approved_callback end |
#on_join_request_created_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_join_request_created_callback @on_join_request_created_callback end |
#on_join_request_rejected_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_join_request_rejected_callback @on_join_request_rejected_callback end |
#on_member_invited_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_member_invited_callback @on_member_invited_callback end |
#on_member_joined_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_member_joined_callback @on_member_joined_callback end |
#on_member_joining_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_member_joining_callback @on_member_joining_callback end |
#on_member_removed_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_member_removed_callback @on_member_removed_callback end |
#on_organization_created_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_organization_created_callback @on_organization_created_callback end |
#on_ownership_transferred_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_ownership_transferred_callback @on_ownership_transferred_callback end |
#on_role_changed_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_role_changed_callback @on_role_changed_callback end |
#on_verification_delivery_failed_callback ⇒ Object (readonly)
Callbacks ===
247 248 249 |
# File 'lib/organizations/configuration.rb', line 247 def on_verification_delivery_failed_callback @on_verification_delivery_failed_callback end |
#parent_controller ⇒ Object
Base controller for authenticated routes (default: ::ApplicationController)
219 220 221 |
# File 'lib/organizations/configuration.rb', line 219 def parent_controller @parent_controller end |
#public_controller ⇒ Object
Base controller for public routes like invitation acceptance (default: ActionController::Base) Use this to avoid inheriting host app filters that enforce authentication
223 224 225 |
# File 'lib/organizations/configuration.rb', line 223 def public_controller @public_controller end |
#public_controller_helpers ⇒ Object
Host helper modules to mix into the PUBLIC engine controller — it inherits ActionController::Base (not the host ApplicationController), so host layouts rendered by public pages need their helper modules declared here. Array of module names (Strings, constantized lazily at controller load — safe to set in an initializer) or Modules.
239 240 241 |
# File 'lib/organizations/configuration.rb', line 239 def public_controller_helpers @public_controller_helpers end |
#public_controller_layout ⇒ Object
Layout for public engine controllers (PublicInvitationsController, etc.) Can be nil (use controller default), String, or Symbol
231 232 233 |
# File 'lib/organizations/configuration.rb', line 231 def public_controller_layout @public_controller_layout end |
#redirect_path_after_invitation_accepted ⇒ Object
Where to redirect after invitation is accepted Can be nil (use default: root_path), a String ("/dashboard"), or a Proc receiving (invitation, user)
173 174 175 |
# File 'lib/organizations/configuration.rb', line 173 def redirect_path_after_invitation_accepted @redirect_path_after_invitation_accepted end |
#redirect_path_after_organization_switched ⇒ Object
Where to redirect after organization switch Can be nil (use default: root_path), a String ("/dashboard"), or a Proc receiving (organization, user)
178 179 180 |
# File 'lib/organizations/configuration.rb', line 178 def redirect_path_after_organization_switched @redirect_path_after_organization_switched end |
#redirect_path_when_invitation_requires_authentication ⇒ Object
Invitation Flow Redirects ===
Where to redirect unauthenticated users when they try to accept an invitation Can be nil (use default: new_user_registration_path or root_path), a String ("/users/sign_up"), or a Proc receiving (invitation, user)
168 169 170 |
# File 'lib/organizations/configuration.rb', line 168 def redirect_path_when_invitation_requires_authentication @redirect_path_when_invitation_requires_authentication end |
#redirect_path_when_no_organization ⇒ Object
Redirects ===
Where to redirect when user has no organization
150 151 152 |
# File 'lib/organizations/configuration.rb', line 150 def redirect_path_when_no_organization @redirect_path_when_no_organization end |
#session_key ⇒ Object
Session/Switching ===
Session key for storing current organization ID
146 147 148 |
# File 'lib/organizations/configuration.rb', line 146 def session_key @session_key end |
#trust_confirmed_account_email ⇒ Object
Allow Organization#join_with_account_email! to trust a host user's already-confirmed account email (e.g. Devise :confirmable) as proof of inbox control, skipping the emailed code when the domain matches.
125 126 127 |
# File 'lib/organizations/configuration.rb', line 125 def trust_confirmed_account_email @trust_confirmed_account_email end |
#unauthorized_handler ⇒ Object (readonly)
Handlers (blocks) ===
243 244 245 |
# File 'lib/organizations/configuration.rb', line 243 def @unauthorized_handler end |
#user_class ⇒ Object
Authentication ===
Class name of the host's user model (default: "User").
Set this when your account model is named differently:
config.user_class = "Account"
⚠️ Configure this BEFORE the gem's models are first referenced: the class name is read when each model class body executes. In Rails this is automatic (initializers run before Zeitwerk autoloads the models); in plain-Ruby usage, call Organizations.configure before touching Organizations::Organization & friends.
⚠️ The install generator's migrations reference to_table: :users —
if your user model uses a different table, adjust the generated
migration accordingly (see the comment inside the migration template).
43 44 45 |
# File 'lib/organizations/configuration.rb', line 43 def user_class @user_class end |
#verification_code_ttl ⇒ Object
How long an emailed verification code stays valid. Must be a Duration/Numeric — codes always expire (OTP hygiene).
106 107 108 |
# File 'lib/organizations/configuration.rb', line 106 def verification_code_ttl @verification_code_ttl end |
#verification_email_normalizer ⇒ Object
Custom email normalizer for the verified_email uniqueness invariant. nil = use Organizations::EmailNormalizer (downcase + strip + drop +tag). Can be a Proc/Lambda: ->(email) { ... } returning the normalized string.
120 121 122 |
# File 'lib/organizations/configuration.rb', line 120 def verification_email_normalizer @verification_email_normalizer end |
#verification_mailer ⇒ Object
Verified Joining ===
Custom mailer for email-verification codes (class name as string)
102 103 104 |
# File 'lib/organizations/configuration.rb', line 102 def verification_mailer @verification_mailer end |
#verification_max_attempts ⇒ Object
Maximum wrong-code attempts per challenge before it locks
109 110 111 |
# File 'lib/organizations/configuration.rb', line 109 def verification_max_attempts @verification_max_attempts end |
#verification_max_sends ⇒ Object
Maximum number of code sends per join request
115 116 117 |
# File 'lib/organizations/configuration.rb', line 115 def verification_max_sends @verification_max_sends end |
#verification_resend_interval ⇒ Object
Minimum time between (re)sends of a verification code for one request
112 113 114 |
# File 'lib/organizations/configuration.rb', line 112 def verification_resend_interval @verification_resend_interval end |
Instance Method Details
#engine_route_groups ⇒ Array<Symbol>
The resolved set of enabled groups.
214 215 216 |
# File 'lib/organizations/configuration.rb', line 214 def engine_route_groups @engine_routes || ENGINE_ROUTE_GROUPS end |
#normalize_verification_email(email) ⇒ String
Normalize an email through the configured (or default) normalizer
506 507 508 509 510 511 |
# File 'lib/organizations/configuration.rb', line 506 def normalize_verification_email(email) normalizer = @verification_email_normalizer return normalizer.call(email).to_s if normalizer.respond_to?(:call) EmailNormalizer.normalize(email) end |
#on_join_request_approved {|context| ... } ⇒ Object
Called when a join request is approved (manually or auto-approved). NOTE: like all after-callbacks, errors here are isolated — hosts must enforce hard caps (e.g. member limits) BEFORE approving, in their own code.
456 457 458 |
# File 'lib/organizations/configuration.rb', line 456 def on_join_request_approved(&block) @on_join_request_approved_callback = block if block_given? end |
#on_join_request_created {|context| ... } ⇒ Object
Called when a join request is created (request-to-join workflow)
447 448 449 |
# File 'lib/organizations/configuration.rb', line 447 def on_join_request_created(&block) @on_join_request_created_callback = block if block_given? end |
#on_join_request_rejected {|context| ... } ⇒ Object
Called when a join request is rejected
463 464 465 |
# File 'lib/organizations/configuration.rb', line 463 def on_join_request_rejected(&block) @on_join_request_rejected_callback = block if block_given? end |
#on_member_invited {|context| ... } ⇒ Object
Called when a member is invited
381 382 383 |
# File 'lib/organizations/configuration.rb', line 381 def on_member_invited(&block) @on_member_invited_callback = block if block_given? end |
#on_member_joined {|context| ... } ⇒ Object
Called when a member joins (invitation accepted)
419 420 421 |
# File 'lib/organizations/configuration.rb', line 419 def on_member_joined(&block) @on_member_joined_callback = block if block_given? end |
#on_member_joining {|context| ... } ⇒ Object
THE MEMBERSHIP GATE — called STRICTLY, inside the creating transaction, immediately BEFORE any non-owner membership row is inserted, on EVERY join path: add_member!, invitation acceptance, join-request approval (which covers join codes, domain-email verification, allowlists, and join_with_account_email!). Raise Organizations::MembershipVetoed (or any error) to veto: the transaction rolls back cleanly — no membership, join requests stay pending (resumable), invitations stay unaccepted.
This is where hard limits belong (plan seat caps, per-org member caps, compliance holds). Unlike on_member_joined and the other after-callbacks (error-isolated by design), this one CAN and SHOULD abort the operation. It deliberately does NOT fire for owner memberships created with the organization itself (creating your own org is not "joining"), nor for idempotent already-a-member paths, nor for role changes.
412 413 414 |
# File 'lib/organizations/configuration.rb', line 412 def on_member_joining(&block) @on_member_joining_callback = block if block_given? end |
#on_member_removed {|context| ... } ⇒ Object
Called when a member is removed
426 427 428 |
# File 'lib/organizations/configuration.rb', line 426 def on_member_removed(&block) @on_member_removed_callback = block if block_given? end |
#on_no_organization {|context| ... } ⇒ Object
Configure no organization handler
365 366 367 |
# File 'lib/organizations/configuration.rb', line 365 def on_no_organization(&block) @no_organization_handler = block if block_given? end |
#on_organization_created {|context| ... } ⇒ Object
Called when an organization is created
374 375 376 |
# File 'lib/organizations/configuration.rb', line 374 def on_organization_created(&block) @on_organization_created_callback = block if block_given? end |
#on_ownership_transferred {|context| ... } ⇒ Object
Called when ownership is transferred
440 441 442 |
# File 'lib/organizations/configuration.rb', line 440 def on_ownership_transferred(&block) @on_ownership_transferred_callback = block if block_given? end |
#on_role_changed {|context| ... } ⇒ Object
Called when a member's role changes
433 434 435 |
# File 'lib/organizations/configuration.rb', line 433 def on_role_changed(&block) @on_role_changed_callback = block if block_given? end |
#on_unauthorized {|context| ... } ⇒ Object
Configure unauthorized access handler
352 353 354 |
# File 'lib/organizations/configuration.rb', line 352 def (&block) @unauthorized_handler = block if block_given? end |
#on_verification_delivery_failed {|context| ... } ⇒ Object
Called when a verification-code email FAILS to enqueue/deliver. The gem already rolls the challenge's throttle bookkeeping back (so the user can retry immediately) — this hook is the host's observability seam: report to your error tracker (Rails.error, Sentry, …) so silent mail outages don't strand joiners.
475 476 477 |
# File 'lib/organizations/configuration.rb', line 475 def on_verification_delivery_failed(&block) @on_verification_delivery_failed_callback = block if block_given? end |
#resolve_default_organization_name(user) ⇒ String
Resolve the default organization name for a user
516 517 518 519 520 521 522 523 524 525 |
# File 'lib/organizations/configuration.rb', line 516 def resolve_default_organization_name(user) case @default_organization_name when Proc @default_organization_name.call(user) when String @default_organization_name else "Personal" end end |
#roles { ... } ⇒ Object
Define custom roles with permissions
495 496 497 498 499 500 501 |
# File 'lib/organizations/configuration.rb', line 495 def roles(&block) if block_given? @custom_roles_definition = block # Reset cached permissions so new roles take effect Roles.reset! end end |
#validate! ⇒ Object
Validate the configuration
529 530 531 532 533 534 535 536 537 538 |
# File 'lib/organizations/configuration.rb', line 529 def validate! validate_authentication_methods! validate_invitation_settings! validate_verification_settings! validate_limits! validate_invitation_redirects! validate_controller_layouts! true end |