Show Right Column to Right User - database

If I have three different user with different occupation (manager, salesman, accounting)
The main question is to how display right column to right person based on star schema and requirement below in SQL server?
The fact and dim are using regular table inside of data mart.
Background information:
The manager is authorized to see all column in factTransaction
The salesman is not allowed to see TaxAmount, TotalAmount and ProductBusinessKey.
The Accounting is note allowed to see Product Quantity, ProductPrice and GeographyFullname.
In windows, the they have their own user account.
The picture is take from the address (Design of a data warehouse with more than one fact tables)

SQL Server does have the ability to assign column permissions (http://msdn.microsoft.com/en-us/library/ms180341%28v=sql.105%29.aspx). You can set the specific permissions as you like, by treating each column as an object with its own security.
Managing column level security is likely to be cumbersome, because you have to remember to update the security every time the table changes and new users are added.
You consider a different approach. Define a separate view for each of the different groups. Only the manager would have access to the "manager" view; only the salesman (and the manager perhaps) would have access to salesman view and so on. Then build the application for each group based on those views.
Finally, managing multiple views might be a bit cumbersome. Instead, you can also have a table-valued function that wraps all the views into a single function. The function would check the permissions for each user and choose the appropriate data to return.
The advantage of user defined functions is that only the user who created the function needs to have access to the underlying tables. That is, the users only have permissions for the function; otherwise, they cannot see the underlying tables. The function would control what they can see.

Related

Database help, one table & multiple users, where CRUD permission depends on column value used

I'm developing a call ticketing system for a hospital, where multiple users from different branches do CRUD activity on one table. This table has relationship restricted value column called, let say [BranchId]. There are three different type of users,
A. Ticket Manager (where they can CRUD without restriction),
B. Ticket Issuer (where they can issue/view/delete tickets but they can't resolve)
C. Ticket Resolver (where they can view/resolve/delete tickets but they can't issue).
So for example,
A patient, who has an appointment with [BranchId] 1, calls to the hospital, and wants to cancel their appointment,
A Ticket Issuer answers the phone and adds this event onto the ticket table and assigns it to [BranchId]=1.
Then the colleagues who work on [BranchId]=1 (they can only see dataset with [BranchId]=1) views the data and resolves (sets the [IsResolved] column to 1)
The patient gets a phone call to notify that their appointment was cancelled.
Solutions so far I can think of
Table Triggers:-
The Ticket Manager adds all users into a table, let say called [BranchUsers] and this table as a column called [Username] where this is populated with Domain\Username, [IsIssuer], [IsResolver] and [BranchId]. The ticket table now has a CRUD trigger when it checks if SYSTEM_USER can issue/resolve and their branch. A separate View table would be used to select from the ticket table with INNER JOIN on [BranchId] for the SYSTEM_USER. However, the problem with this approach is that users can select data directly from the ticket table and so be able to read everything in the table and the [BranchUsers] table may be hard to maintain but that is ok.
Using Active Directory Group:-
So in the Windows Server AD Group, create a group called, let say [Branch1Users], [Branch2Users] etc..., and create multiple ticket tables... you see now it got complex as if one table need some changing such as renaming a column, then the .NET Core API references need too and going back to the Trigger approach above seems easier.
So what would you think be best, please advice anything even if you think it might not help as it may help create a light bulb ideas, I will start the trigger approach for now as this project has deadline soon :-)
Specs that might help:-
Microsoft SQL Server 2019
Windows Server 2019

How to Restrict access to fields in a database

In a database (Microsoft Access, Relational), is it possible to restrict access to a specific field in a table for a certain group?
So the group would have access to the table but not see one of the fields?
If not, is the only way to do this by seperating the data into another table and restricting it for this group?
You can not restrict access to a specific field.
However, you can create a query based off a table. And you can also set a table's "Visible" property to "No". This isn't foolproof; if the user knows how to change the properties of a table then they can change it back to "Visible".
There really is no 100% foolproof way to lock down an Access database entirely. However, you can make it awfully difficult by hiding the objects, hiding the database and bypassing the CTRL key (to avoid the old Shift/CTRL trick).
You can create different views for difference users | users group with only required columns that they should allow to access. Then grant permission for users/user groups on those views accordingly.

Advanced user info in database

I'm creating an Account table in my project's database. Each account has A LOT of properties:
login
email
password
birthday
country
avatarUrl
city
etc.
Most of them are nullable. My question is, how should I design this in database?
Should it be one table with all those properties? Or maybe should I create two tables, like AccountSet, and AccountInfoSet, where I would store all those 'advanced' user's settings? And last, but not least: if this should be two tables, what kind of relation should be between those tables?
If this is a relational database, then I definitely would not store those properties as fields in the Account table. Some reasons why:
Once your application goes to production (or maybe it's already there), the schema maintenance will become a nightmare. You will absolutely add more properties and having to constantly touch that table in production will be painful.
You will most likely end up with orphaned fields. I've seen this many times where you'll introduce a property and then stop using it, but it's baked into your schema and you might be too scared to remove it.
Ideally you want to avoid having such sparse data in a table (lots of fields with lots of nulls).
My suggestion would be to do what you're already thinking about and that's to introduce a property table for Accounts. You called it AccountInfoSet.
The table should look like this:
AccountId int,
Property nvarchar(50),
Value nvarchar(50)
(Of course you'll set the data types and sizes as you see fit.)
Then you'll join to the AccountInfoSet table and maybe pivot on the "advanced" properties - turn the rows into columns with a query.
In .NET you can also write a stored procedure that returns two queries with one call and look at the tables in the DataSet object.
Or you could just make two separate calls. One for Account and one for the properties.
Lots of ways to get the information out, but make sure you don't just add fields to Account if you're using a relational database.

inserting into a view in SQL server

I have a SQL Server as backend and use ms access as frontend.
I have two tables (persons and managers), manager is derived from persons (a 1:1 relation), thus i created a view managersFull which is basically a:
SELECT *
FROM `managers` `m`
INNER JOIN `persons` `p`
ON `m`.`id` = `p`.`id`
id in persons is autoincrementing and the primary key, id in managers is the primary key and a foreign key, referencing persons.id
now i want to be able to insert a new dataset with a form in ms access, but i can’t get it to work. no error message, no status line, nothing. the new rows aren’t inserted, and i have to press escape to cancel my changes to get back to design view in ms access.
i’m talking about a managers form and i want to be able to enter manager AND person information at the same time in a single form
my question is now: is it possible what i want to do here? if not, is there a “simple” workaround using after insert triggers or some lines of vba code?
thanks in advance
The problem is that your view is across several tables. If you access multiple tables you could update or insert in only one of them.
Please also check the MSDN for more detailed information on restrictions and on proper strategies for view updates
Assuming ODBC, some things to consider:
make sure you have a timestamp field in the person table, and that it is returned in your managers view. You also probably need the real PK of the person table in the manager view (I'm assuming your view takes the FK used for the self-join and aliases it as the ID field -- I wouldn't do that myself, as it is confusing. Instead, I'd use the real foreign key name in the managers view, and let the PK stand on its own with its real name).
try the Jet/ACE-specific DISTINCTROW predicate in your recordsource. With Jet/ACE back ends, this often makes it possible to insert into both tables when it's otherwise impossible. I don't know for certain if Jet will be smart enough to tell SQL Server to do the right thing, though.
if neither of those things works, change your form to use a recordsource based on your person table, and use a combo box based on the managers view as the control with which you edit the record to relate the person to a manager.
Ilya Kochetov pointed out that you can only update one table, but the work-around would be to apply the updates to the fields on one table and then the other. This solution assumes that the only access you have to these two tables is through this view and that you are not allowed to create a stored procedure to take care of this.
To model and maintain two related tables in access you don’t use a query or view that is a join of both tables. What you do is use a main form, and drop in a sub-form that is based on the child table. If the link master and child setting in the sub-form is set correctly, then you not need to write any code and access will insert the person’s id in the link field.
So, don’t use a joined table here. Simply use a form + sub-form setup and you be able to edit and maintain the data and the data in the related child table.
This means you base the form on the table, and not a view. And you base the sub-form on the child table. So, don't use a view here.

Table Module vs. Domain Model

I asked about Choosing a method to store user profiles the other day and received an interesting response from David Thomas Garcia suggesting I use the Table Module design pattern. It looks like this is probably the direction I want to take. Everything I've turned up with Google seems to be fairly high level discussion, so if anyone could point me in the direction of some examples or give me a better idea of the nuts and bolts involved that would be awesome.
The best reference is "Patterns of Enterprise Application Architecture" by Martin Fowler:
Here's an excerpt from the section on Table Module:
A Table Module organizes domain
logic with one class per table in the
database, and a single instance of a
class contains the various procedures
that will act on the data. The
primary distinction with Domain
Model is that, if you have many
orders, a Domain Model will have one
order object per order while a Table
Module will have one object to handle
all orders.
Table Module would be particularly useful in the flexible database architecture you have described for your user profile data, basically the Entity-Attribute-Value design.
Typically, if you use Domain Model, each row in the underlying table becomes one object instance. Since you are storing user profile information in multiple rows, then you end up having to create many Domain Model objects, whereas what you really want is one object that encapsulates all the user properties.
Instead, the Table Module makes it easier for you to code logic that applies to multiple rows in the underlying database table. If you create a profile for a given user, you'd specify all those properties, and the Table Module class would have the code to translate that into a series of INSERT statements, one row per property.
$table->setUserProfile( $userid, array('firstname'=>'Kevin', 'lastname'=>'Loney') );
Likewise, querying a given user's profile would use the Table Module to map the multiple rows of the query result set to object members.
$hashArray = $table->getUserProfile( $userid );

Resources