Module: Milia::Base::ClassMethods
- Defined in:
- lib/milia/base.rb
Overview
############################################################################# #############################################################################
Instance Method Summary collapse
-
#acts_as_tenant ⇒ Object
———————————————————————— acts_as_tenant – makes a tenanted model Forces all references to be limited to current_tenant rows ————————————————————————.
-
#acts_as_universal ⇒ Object
———————————————————————— acts_as_universal – makes a univeral (non-tenanted) model Forces all reference to the universal tenant (nil) ————————————————————————.
-
#acts_as_universal_and_determines_account ⇒ Object
———————————————————————— acts_as_universal_and_determines_tenant_reference All the characteristics of acts_as_universal AND also does the magic of binding a user to a tenant ————————————————————————.
-
#acts_as_universal_and_determines_tenant ⇒ Object
———————————————————————— ————————————————————————.
-
#current_tenant ⇒ Object
————————————————————————.
-
#current_tenant_id ⇒ Object
———————————————————————— current_tenant_id – returns tenant_id for current tenant ————————————————————————.
-
#set_current_tenant(tenant) ⇒ Object
———————————————————————— set_current_tenant – model-level ability to set the current tenant NOTE: *USE WITH CAUTION* normally this should NEVER be done from the models …
-
#where_restrict_tenant(*args) ⇒ Object
———————————————————————— where_restrict_tenant – gens tenant restrictive where clause for each klass NOTE: subordinate join tables will not get the default scope by Rails theoretically, the default scope on the master table alone should be sufficient in restricting answers to the current_tenant alone ..
Instance Method Details
#acts_as_tenant ⇒ Object
acts_as_tenant – makes a tenanted model Forces all references to be limited to current_tenant rows
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/milia/base.rb', line 16 def acts_as_tenant() belongs_to :tenant validates_presence_of :tenant_id default_scope lambda { where( "#{table_name}.tenant_id = ?", Thread.current[:tenant_id] ) } # ..........................callback enforcers............................ before_validation(:on => :create) do |obj| # force tenant_id to be correct for current_user obj.tenant_id = Thread.current[:tenant_id] true # ok to proceed end # ..........................callback enforcers............................ before_save do |obj| # force tenant_id to be correct for current_user # raise exception if updates attempted on wrong data raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id == Thread.current[:tenant_id] true # ok to proceed end # ..........................callback enforcers............................ # no longer needed because before_save invoked prior to before_update # # before_update do |obj| # force tenant_id to be correct for current_user # raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id == Thread.current[:tenant_id] # true # ok to proceed # end # ..........................callback enforcers............................ before_destroy do |obj| # force tenant_id to be correct for current_user raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id == Thread.current[:tenant_id] true # ok to proceed end end |
#acts_as_universal ⇒ Object
acts_as_universal – makes a univeral (non-tenanted) model Forces all reference to the universal tenant (nil)
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/milia/base.rb', line 55 def acts_as_universal() belongs_to :tenant default_scope { where( "#{table_name}.tenant_id IS NULL" ) } # ..........................callback enforcers............................ before_save do |obj| # force tenant_id to be universal raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id.nil? true # ok to proceed end # ..........................callback enforcers............................ # before_update do |obj| # force tenant_id to be universal # no longer needed because before_save invoked prior to before_update # # raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id.nil? # true # ok to proceed # end # ..........................callback enforcers............................ before_destroy do |obj| # force tenant_id to be universal raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id.nil? true # ok to proceed end end |
#acts_as_universal_and_determines_account ⇒ Object
acts_as_universal_and_determines_tenant_reference All the characteristics of acts_as_universal AND also does the magic of binding a user to a tenant
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/milia/base.rb', line 87 def acts_as_universal_and_determines_account() include ::Milia::InviteMember has_and_belongs_to_many :tenants acts_as_universal() # validate that a tenant exists prior to a user creation before_create do |new_user| if Thread.current[:tenant_id].blank? || !Thread.current[:tenant_id].kind_of?(Integer) || Thread.current[:tenant_id].zero? raise ::Milia::Control::InvalidTenantAccess,"no existing valid current tenant" end end # before create callback do # before create, tie user with current tenant # return true if ok to proceed; false if break callback chain after_create do |new_user| tenant = Tenant.find( Thread.current[:tenant_id] ) unless tenant.users.include?(new_user) tenant.users << new_user # add user to this tenant if not already there end end # before_create do before_destroy do |old_user| old_user.tenants.clear # remove all tenants for this user true end # before_destroy do end |
#acts_as_universal_and_determines_tenant ⇒ Object
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/milia/base.rb', line 123 def acts_as_universal_and_determines_tenant() has_and_belongs_to_many :users acts_as_universal() before_destroy do |old_tenant| old_tenant.users.clear # remove all users from this tenant true end # before_destroy do end |
#current_tenant ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/milia/base.rb', line 138 def current_tenant() begin tenant = ( Thread.current[:tenant_id].blank? ? nil : Tenant.find( Thread.current[:tenant_id] ) ) return tenant rescue ActiveRecord::RecordNotFound return nil end end |
#current_tenant_id ⇒ Object
current_tenant_id – returns tenant_id for current tenant
156 157 158 |
# File 'lib/milia/base.rb', line 156 def current_tenant_id() return Thread.current[:tenant_id] end |
#set_current_tenant(tenant) ⇒ Object
set_current_tenant – model-level ability to set the current tenant NOTE: *USE WITH CAUTION* normally this should NEVER be done from the models … it’s only useful and safe WHEN performed at the start of a background job (DelayedJob#perform)
166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/milia/base.rb', line 166 def set_current_tenant( tenant ) # able to handle tenant obj or tenant_id case tenant when Tenant then tenant_id = tenant.id when Integer then tenant_id = tenant else raise ArgumentError, "invalid tenant object or id" end # case old_id = ( Thread.current[:tenant_id].nil? ? '%' : Thread.current[:tenant_id] ) Thread.current[:tenant_id] = tenant_id logger.debug("MILIA >>>>> [Tenant#change_tenant] new: #{tenant_id}\told:#{old_id}") unless logger.nil? end |
#where_restrict_tenant(*args) ⇒ Object
where_restrict_tenant – gens tenant restrictive where clause for each klass NOTE: subordinate join tables will not get the default scope by Rails theoretically, the default scope on the master table alone should be sufficient in restricting answers to the current_tenant alone .. HOWEVER, it doesn’t feel right. adding an additional .where( where_restrict_tenants(klass1, klass2,…)) for each of the subordinate models in the join seems like a nice safety issue.
191 192 193 |
# File 'lib/milia/base.rb', line 191 def where_restrict_tenant(*args) args.map{|klass| "#{klass.table_name}.tenant_id = #{Thread.current[:tenant_id]}"}.join(" AND ") end |