问题
I'm working on a Django project which will take on firms as clients and each client will be allowed to create multiple users. These users can then be assigned different permissions or roles.
The catch being that the type of permissions vary with clients i.e. they're not as simple as read, write, delete. Hence one client can have only 5-10 types of permissions while the other can have 100's.
The inbuilt Django permissions framework does not directly support my usecase, so this is what I came up with:
- Create a main django app which houses the user model
- For every new client, create a new django app with only models.py
- The models.py has only one model (for the time being) that in itself houses the permissions specific to that client as explained here.
- Now I can assign each user permissions depending on which client the user is a part of.
While I haven't tested it, this should work. The solution looks scalable but there are a lot of inconsistencies and it doesn't seem like the right way to do it. Is there a work around?
Update: django-guardian looks like it could help, not sure how.
Update: I think I'll explain the entire architecture because the current solution does not work directly for it.
- There are time series data streams with data coming in at regular intervals. Each client can have anywhere between 100 to more than 1000 such streams. These streams are not however saved in the webservers DB but are saved in each clients different DB.
- Now, a user can have privileges to view either all, one, or some of the above streams. The client lets us know about the type of user they want to create and we create one accordingly.
- For authentication purposes, its better to have all users in one table. But for authorization it makes sense to have each clients users on a separate table. It's best, in my opinion, to segregate the clients.
- Slightly off topic, but we were looking at providing each client with a separate co-domain like client1.mysite.com, client2.mysite.com etc and hence we have the freedom to deploy different web servers for each client and hence customize it for each client. Also, this helps in storing the data of each clients users differently.
回答1:
I really don't like your solution - it is similar to old database designs where schema chnges were expected by design !!! Please, whatever the cost DON'T do it. Forgetting about django, 40 years of database design has tought us that the schema of the database should never change (unless of course the requirements change or your design was not correct). I could provide an answer similar to this: RegEx match open tags except XHTML self-contained tags to emphasize how important is to not change your database schema.
So, you will have a django app which houses the user model as you say and a CustomPermission
model which will give an interface to the admininstrator so that he will add permissions for eah client (the administrator will add the permissions for the client, not the developer). Each CustomPermission
will just have a name and a ForeignKey
to the client it applies.
Now you can create a UserCustomPermission
model which will have a ForeignKey
to the User
and another ForeignKey
to the CustomPermission
(actually there is a many-to-many relation between User
and CustomPermission
.
Now, what you need to implement is how the permissions you assign will be assigned to actual allowed and forbidded actions. You don't say anything about this in your question. Just to give you a direction, I really like (and use all the time) the django-rules-light application (https://github.com/yourlabs/django-rules-light) which can be used to define your business rules.
Probably my answer doesn't actually solve your problem, or maybe I didn't understand something, but I believe that you will get a starting point -- also feel free to update your question and I'll update my answer accordingly.
Answer to the update
As you can understand, I don't like 1 and 3: For every new client you will need to create a new database ? Why not put all your client streams in the same table and use a foreign key to the client they belong to ?
(HERE BE DRAGONS)
I thought a nice solution - I wouldn't do it, but if want so much to put your users and their permissions in different databases then you can use the seperate sub-domain in your advance: Use database routing (https://docs.djangoproject.com/en/1.3/topics/db/multi-db/#database-routers) to select each client's database depending on the sub-domain. So, you will define all your client's databases in your settings.py:
DATABASES = { 'default': { 'NAME': 'app_data', 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'USER': 'postgres_user', 'PASSWORD': 's3krit' }, 'client1': { 'NAME': 'client2', 'ENGINE': 'django.db.backends.mysql', 'USER': 'client2', 'PASSWORD': 'priv4te' }, 'client2': { 'NAME': 'client1', 'ENGINE': 'django.db.backends.mysql', 'USER': 'client1', 'PASSWORD': 'priv4te' } }
And then you will create a SubDomainDatabaseRouter
class that will use the correct database depending on your sub-domain. Because the request settings are not available in that class you have to put them there by using middleware and thread locals. Take a look at the following snippet
https://djangosnippets.org/snippets/2037/
So in your RouterMiddleware
you will check to see the subdomain and depending on that you will set a client_cfg
option with the name of the client. Your SubDomainDatabaseRouter
will use the correct database depending on the client_cfg
. To use it just add
DATABASE_ROUTERS = ['my.package.SubDomainDatabaseRouter']
By using this you will have a completely different database for each client. I need to emphasize again that you will have a hell maintaining it - let's suppose you have 100 clients and need to add a field to a table. Then what ? Please don't blame me :)
(END OF DRAGONS)
来源:https://stackoverflow.com/questions/20641392/django-permissions-for-different-clients