-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
restore tenant_id enforcement in modern rails #3674
base: master
Are you sure you want to change the base?
Conversation
It's probably worth keeping it because we had related incidents in the past that could have been detected earlier if this check would have worked. |
194b529
to
4b2082a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to understand this, but I need some help:
- On startup, this module is initialized from
Line 273 in bde8321
config.middleware.use ThreeScale::Middleware::Multitenant, :tenant_id - Then, the
EnforceTenant
module is included in all models (I think it would be more correct to useApplicationRecord
thanActiveRecord::Base
)porta/lib/three_scale/middleware/multitenant.rb
Lines 101 to 105 in 46b2f9b
def initialize(app, attribute) @app = app @attribute = attribute ActiveRecord::Base.send(:include, EnforceTenant) end - Every time a new model is created,
:enforce_tenant!
is called. I assumeThread.current[:multitenant]
will always have the correct value here. Then it callsverify!
- The module name
EnforceTenant
makes me think the purpose is to ensure:tenant_id
will always have a value, but from the code atverify!
it seems to me it only checks the value doesn't change. So this assumes:tenant_id
is set somewhere else and this only makes sure it never changes. Am I right? - In this snippet,
porta/lib/three_scale/middleware/multitenant.rb
Lines 44 to 50 in 46b2f9b
begin current = object.send(attribute) rescue ActiveRecord::MissingAttributeError # Multitenant.log("#{object} is missing #{attribute}. Reloading and trying again") fresh = object.class.send(:with_exclusive_scope) { object.class.find(object.id, :select => attribute) } current = fresh.send(attribute) end rescue ActiveRecord::MissingAttributeError
when callingcurrent = fresh.send(attribute)
? Is it a bug?
If the purpose is to make sure :tenant_id
doesn't change, couldn't this be done in a much easier way? e.g. I found this:
https://discuss.rubyonrails.org/t/validates-immutable-true/81479/2
extend ActiveSupport::Concern | ||
|
||
included do | ||
after_initialize :enforce_tenant! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better
How did you conclude that code checkd |
Maybe I'm wrong because I don't understand the code. I guessed that from this code: porta/lib/three_scale/middleware/multitenant.rb Lines 56 to 72 in 46b2f9b
If |
4b2082a
to
df9873b
Compare
if (user_id = @session.last[:user_id].presence) | ||
@users ||= {} | ||
@users[user_id] ||= User.find_by_sql(["SELECT * FROM users WHERE id = ? AND account_id = ?", user_id, @master.id]).present? | ||
return if @users[user_id] | ||
end | ||
# this is supposed to match how we get the user_session in app/lib/authenticated_system/request.rb | ||
# on API calls cookies are not present though, so we need to use safe navigation | ||
@user_session ||= UserSession.authenticate(@env['action_dispatch.cookies']&.signed&.public_send(:[], :user_session)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting question here is why originally we kept user_id
in a hash. As if we may observe multiple user_ids within the same request. Which doesn't make sense to me. Any ideas?
This is set once for each request here:
The purpose is to make sure that a user only sees objects from its own tenant. The implementation seems to be that first initialized object with a
I don't think it is a bug. Because we retrieve the necessary attribute when we obtain the object. That's the point of the
I need more elaboration to understand how this applies. |
df9873b
to
c77c92d
Compare
fixes THREESCALE-10686
c77c92d
to
4e55969
Compare
needs tests before merging and also we should consider whether this is needed at all at this point
fixes THREESCALE-10686