On Nov 16, 2:41 am, "ARAI Shunichi" <[EMAIL PROTECTED]> wrote:
> Hi all,
>
> Right now, I'm writing a code for a SaaS application.
>
> I'm thinking about an idea to enforce a security restriction to Sequel
> Models by changing dataset filter dynamically.
>
> If current user's id is 123, then I want to apply filter(:user_id => 123) to
> all models related to users table.
>
> Probably it can be achieved with following example code:
>
> def load_session(user_id)
> foo = DB[:foo].filter(:user_id => user_id)
> Foo.set_dataset(foo)
> end
>
> Problems are
> * Performance impact of changing dataset for every access is not clear.
> * Not sure that it's okay to re-use model classes many times with different
> datasets.
> * This implementation is thread unsafe, abusing global environment, and I
> feel it's quite ugly.
>
> Any ideas?
You are correct, it is ugly, thread unsafe, and generally just a bad
idea. Here's a better approach:
Model.def_dataset_method(:user){|id| filter(:user_id=>id)}
Then you can just use:
Model.user(user_id)...
instead of
Model...
> My idea is that extending Sequel to enable having non-class (instance)
> models.
>
> Right now, all Sequel models are defined in global classes with global
> database setting. I think it'll be useful if we can have model object such
> as:
>
> foo_model = database.define_model(Foo, dataset)
>
> I think it's useful for multi-database applications too. It'll be great if
> dataset defining overhead is not big.
You could do that now, if you wanted to:
foo_model = Class.new(Sequel::Model(Foo))
foo_model.dataset.filter!(:user_id=>user_id)
I also think this is a bad idea, though.
> Or, simply just adding filtering to Model, like:
>
> foo_filtered = Foo.filter_model(:user_id => 123)
>
> Currently, Foo.filter returns a dataset, not a model. If it behaves like a
> model, it'll be great for me. I'd like to write a simple query like
> Foo[foo_id].
Is there a need for it to be a model instead of a dataset? You can
probably get most of the functionality you want by adding some dataset
methods:
Foo.def_dataset_method(:[]){|id| first(:id=>id)}
Foo.user(user_id)[id]
One of the applications I develop is a multi-user accounting system
where most tables have a user_id field and users should only be able
to see things related to them. I took the approach of adding dataset
methods that filter by user_id for all models, and always used
Model.user(user_id) instead of just Model. I made sure the user_id was
always set correctly on object creation. I also added database
triggers to make sure that once a user_id is set, it cannot be
changed. This required a bit more explicit code, but it is a very
robust approach, and it is the approach I recommend.
Jeremy
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en
-~----------~----~----~----~------~----~------~--~---