Is representing user permissions better in the user table or better in its own permissions table?
Permissions in User table
Putting permissions in the user table means making a column for each permission in the user table. An advantage is queries should run faster because no joins are necessary when relating users to user permissions. A disadvantage is that having many permissions columns clutters the user table.
Permissions in Permission table joined to User table with many-to-many relationship
Doing it this way cleanly separates out the permissions from the user table, but it requires a join across two tables to access user permissions. Database access might be slower, but database design seems cleaner.
Perhaps keeping permissions in a separate table is better when there are many permissions. What are other considerations in making this decision, and which design is better in various situations?
The standard pattern for access control is called Role Based Security. As both the number of users and the number of different types of permissions you need grows, the management of your user-to-permissions links can become increasingly difficult.
For example, if you have five administrators and fifty users, how do you keep the permissions of each group in synch? When one of your users is promoted to an administrator, how many edits do you need to make? The answer is to create two intersections: users-to-roles and roles-to-permissions.
This solution is described (including entity relationship diagram) in my answer to this question.
Your first approach is feasible when the number of different roles/permissions is relatively small. For example if you only have two types of users: normal and admin, a separate table looks like an overkill. Single is_admin column is sufficient and simple.
However this approach does not scale once the number of roles exceeds a few. It has several drawbacks:
user table becomes very "wide" having a lot of empty columns (wasting space)
adding new role to the system requires altering user table. This is cumbersome and might be time-consuming for large user database
listing user roles requires enumerating over all columns, as opposed to simple database query.
Related
we are using .net mvc and sqlserver db.
EDIT
We are also using NHibernate for data access. I mention this because we will not be writing our own sql or do stored procs. triggers in the db might work but I don't know if you can do that between databases.
END EDIT
we want to have a multi tenant set up so each client has there own instance of the db. However, we need to have each tenant connect to an other database which has a great deal of user information. there will be some small amount of shared data between them. Basically the tenants will be referencing the data of the users in the shared database.
The idea is that some people will use just the shared database ( independent clients ) they then may well be hired by one of the tenant clients. the tenant will then want access to the new employees data in the shared database. Further the employee may leave one tenant and join another or leave one and remain independent and want access to thier data. We could of course have the shared database schema in each tenant and just do a big export import each time some one left or joined but this seems like a lot of trouble too.
I am asking for any advice on how to manage the fact that the tenants will have references to the shared database but no referential integrity. Or if there is an alternate approach or whatever.
Thank you,
Raif
Across databases you have to give up declarative referential integrity (foreign keys). However you can still enforce this (if you think you need to) using after or instead of triggers, or if you control all data manipulation via stored procedures, you can do it there (on insert or update, for example, you can check first, or as part of the modification join to or use EXISTS against the table(s) in other databases to be sure that a valid value is being used).
I've worked with multi-tenant models and there can be huge benefits that are worth the costs (e.g. giving up DRI in some cases). For things that are mostly reference data and that aren't free-text entry, there shouldn't be a whole lot of extra effort required.
I am not a security expert and there was a discussion in my project about if we should use Entity Framework. Even though it seems we will use it the project leader is instill insisting that we should still do all our operations (that includes simple CRUDs) with store procedures because of security. He says that if we use stored procedures the users will only need permission for executing a stored procedure instead of needing permissions for create/read/update/delete.
As I said before I am not a security expert, so I was curious to know how true is this.
What this does is give rights and privileges to the individual store procedures, which then have access to the tables, rather than to the tables themselves.
This way you can restrict the users from all the tables, and allow the SPs to allow semantic access based on other logic (both DB permissions at the SP level, as well as code within the SP).
This is gives the overall security framework finer granularity in terms of roles and privileges.
For example, using normal DB permissions, it's easy to limit what tables a user can see, but not what rows they can see within a table.
Two ways to fix that is to limit access to the underlying table, and then create a limited view on that table and grant permission to that, or you can limit access via the SP which has logic capable of restricting what rows a user can see.
Its true.
Stored procedures gives ability to perform better security than standard table permission (for example by giving possibility to update only few columns of table)
But..
For developers its a nightmare. Even simplest query needs to be implemented as stored proc or view.
So its not agile, rapid or sexy :)
In Oracle,
- I want to ensure that owner of trigger must match table owner.
- Also the views should be restricted. The user must not be able to query system views and tables.
Generally only the owner of a table will have privileges to create triggers on it. DBAs may have the privilege CREATE ANY TRIGGER, but protecting a database from a DBA is whole different order of question.
There are a number of system views (eg USER_TABLES, ALL_USERS) which you can't revoke access on, but they will only reveal what the user has been granted access to. Again the DBA will have access to views prefixed DBA_ and 'views' prefixed V$ (which are a bit odd in that they show operational information about the database and not data that is stored on disk anywhere) and tables owned by SYS.
What exactly is it that you want to accomplish?
Normally, we create roles that give access to only the application tables and views.
The owner of the application grants privileges to those roles and
the roles are granted to your users.
As long as the owner of the tables only has the regular 'create xxx' privileges, there is not much to worry for. Normally we need access to some system tables and views.
What data do you want to hide? Most of the views don't reveal more than already is known by the application.
Don't give 'xxxx ANY' privileges to anyone. Most of the time when those privs are requested it is because of laziness. They are rarely needed.
Ronald.
Consider a database server whose job today is to house one database. Likely the database will be moved in the future to another database instance which houses multiple databases & schemas.
Let's pretend the app/project is called Invoicer 2.0. The database is called AcmeInvoice. The database holds all the invoice, customer, and product information. Here's a diagram of the actors and their roles and behaviour.
The schema(s) will largely be used to easily assign permissions to roles. The added benefit here is that the objects aren't under dbo, and that the objects & permissions can be ported to another machine in the future.
Question
What conventions do you use when naming the schema?
Is it good form to name the schema the same as the database?
I would think that if your schema name ends up being the same as your database schema, then you are just adding redundancy to your database. Find objects in your database that have common scope or purpose and create a schema to relect that scope. So for example if you have an entity for Invoices, and you have some supporting lookup tables for invoice states, etc, then put them all in an invoice schema.
As a generally rule of thumb, I would try to avoid using a name that reflects the application name, database name or other concrete/physical things because they can change, and find a name that conceptually represents the scope of your objects that will go into the schema.
Your comment states that "the schemas will largely be used to easily assign permissions to roles". Your diagram shows specific user types having access to some/all tables or some/all stored procs. I think trying to organize objects conceptually into schemas and organize them from a security standpoint into schemas are conflicting things. I am in favour of creating roles in sql server to reflect the types of users, and grant those roles access to the specific objects that each user type needs, as apposed to granting the role or user access the schema to build your security framework..
Why would you name the schema the same as the database? This means all database objects fall under the same schema. If this is the case, why have a schema at all?
Typically schema's are used to group objects within a common scope of activity or function. For example, given what you've described, you might have an Invoice schema, a Customer schema and a Product schema. All Invoice related objects would go into the Invoice schema, all Customer related objects would go into the Customer schema, and the same for Products.
We often will use a Common schema as well which includes objects that might be common to our entire application.
I would call the database AcmeInvoice (or another suitable name) and the schema Invoicer2.
My reasons are as follows: Acmeinvoice means I am grouping all of that applications objects/data together. It can therefore be moved as one unit to other machines (a backup/restore or unattach/attach).
The schema would be Invoicer2. Applications change, maybe in the future you will have Invoicer21 (you would create a schema), or perhaps a reporting module or system (Reports schema).
I find that the use of schemas allows me to separate data/procedures in one database into different groups which make it easier to adminster permissions.
I'm working on a web-based business application where each customer will need to have their own data (think basecamphq.com type model) For scalability and ease-of-upgrades, I'd prefer to have a single database where each customer gets a filtered version of the data. The problem is how to guarantee that they stay sandboxed to their own data. Trying to enforce it in code seems like a disaster waiting to happen. I know Oracle has a way to append a where clause to every query based on a login id, but does Postgresql have anything similar?
If not, is there a different design pattern I could use (like creating a view of each table for each customer that filters)?
Worse case scenario, what is the performance/memory overhead of having 1000 100M databases vs having a single 1Tb database? I will need to provide backup/restore functionality on a per-customer basis which is dead-simple on a single database but quite a bit trickier if they are sharing the database with other customers.
You might want to look into adding Veil to your PostgreSQL installation.
Schemas plus inherited tables might work for this, create your master table then inherit tables into per-customer schemas which provide a company ID or name field default.
Set the permissions per schema for each customer and set the schema search path per user. Use the same table names in each schema so that the queries remain the same.