I'm maintaining a system (in Java, with Tomcat, Spring MVC, and Hibernate) where I have to set access rules for user groups. These rules are saved in a database (PostgreSQL) as records / rows. The logic is very simple. Each user of a company's team belongs (is connected) to a group, and each group has a set of rules.
I have to allow administrators to configure (through a web application) rules for groups, so that each rule has a logic and this is recognized and reproduced on the server side.
I need to define rules with parameters, such as:
Authentications only weekends.
Authentications only on weekdays.
Authentications only at a certain time (from time X to time Y).
X authentications per day.
Account expiration from date X
And so on...
My intention is that the company team can organize itself dynamically, just setting up any rules they want at any time, without the need for maintenance every time their policies change.
I've been searching on google and found nothing about it. I know I can do this in Java code, I would have to tie Java code with values of rules names present in database, something that could change in the future (or between companies), and this does not seem right to me. I'm not sure if this is correct, or preferable (maintainable). I appreciate any suggestions, ideas, or corrections (for real).
Note: Team/Groups names may change, but its rules should remain the same (if desired).
EDIT
The database is already modeled and ready. Groups and rules represent values from two different tables, with no logic at all. Querying these values works trivial. However, as I'm maintaining a web application, I'm in charge of creating a code or procedure that applies logic to the choice of rule values.
I was very clear in my question, but I will add more things:
Imagine that my clients (companies) want a website (a web application) that can manage their employees. Every company has teams of employees (groups), each with its function. Otherwise, some employees are sometimes hired as temporary employees.
My duty is to restrict access to the accounts of users who are part of company teams. This will allow business leaders to restrict things according to their policies.
For any company, the process works something like this:
The person in charge defines groups (with names and descriptions).
The same person defines restrictions rules for each group.
User accounts are created and linked to groups with rules.
The accounts are given (assigned) to each person part of the company
team, each according to their function.
Why should this be done?
Management
Control
Security
Speaking more technically now, I do not know where or how I should implement this properly. I know of a way to accomplish this, which is in programming code (Java, in my case), but again, I do not know if this is appropriate.
I also know that it is possible to define users and groups on the database side. But creating and deleting such definitions for each time an employee is hired or his or her length of service is expired can not become practical. My intention is to avoid to the maximum that companies have to spend more money on maintenance (Although sometimes this is obviously impossible).
My question based on a real case can be answered indicating to me an ideal way / approach for this type of scenario, either the solution being something that should be implemented in the database, or something done in the application layer, or both, or something else (I do not have experience to solve this kind of situation properly, so I'm here).
For practical purposes, I have decided to describe what technologies I am using in this system. If you want more information, I'll be happy to show you here.
Also, as this is a question that covers a larger context, not specifically databases, and also not specifically web applications, I have decided to put it here (instead of other StackExchange communities).
Thank you.
Related
I am making an application for a campground that has a list of camping sites, each of which has a list of reservations. There can be any number of reservations for each camping site and any number of camping sites.
I started off by just storing this data in a csv and using that to handle everything. This is working really well because after a few columns of identifying information for each site, I just have an arbitrary number of reservations that I can go through. It's also really easy for me to add a new site if I want to add that functionality to my application since I can just add a new line and leave the reservation part blank if there aren't any reservations.
I'm thinking that I should instead use a database to store this information for the following reasons:
I need to be able to search and modify specific sites in addition to just iterating through them in order. With the CSV solution, iterating through them in order has been great when I need to use them all but I don't want to have to iterate through to find a specific reservation. Plus modifying the csv isn't looking to be that great either.
I am hoping to gain a better understanding of databases in general and I don't believe using a csv is the most professional way to do this, nor would it be the best practice.
How exactly could I do this? If, for example, I had only one camping site then I would just add another table that represents the reservations as an entry to the table but since I have at least 100 camping sites and can have an arbitrary amount, this doesn't seem to make sense. Am I just not understanding something or am I correct in coming to that conclusion?
Some more information:
Since I haven't said it yet, this is a java application with an apache derby database.
This project is not for a class or a job, I'm just trying to practice my programming skills and help someone out who runs a campground at the same time.
There is an application that I'm basically writing with Swing, JDBC and MySQL.
In DB there are tables like Article, Company, Order, Transaction, Client etc.
So also there are java classes which describes them.
User can create, update, delete information about them.
I give an example of my problem. The article characterizes with id, name, price, company, unit. And when user wants to save new article he chooses the company for this article from the list of all companies. This list in perspective could be really big.
Now I could think of two ways to solve this.
When application starts, it connects to the DB and load all the data with which then I will work.
public final class AllInformationController {
public static final Collection<Company> COMPANIES= new HashSet<>(1_000_000);
public static final Collection<Article> ARTICLES= new HashSet<>(1_000_000);
public static final Collection<Order> ORDERS= new HashSet<>(1_000_000);
public static final Collection<Transaction> transactionsHistory= new HashSet<>(10_000_000);
//etc...
private AllInformationController() {}
}
Then if user wants for example to change some Company data (like address or telephone etc.), after doing it the program should update the DB info for that company.
The second approach is basically to connect to the database every time user queries or changes some information. So then I will mostly work with ResultSet's.
I prefer the second way, but just not sure if it's the best one. Think there should be more productive ways to work with data that could be less expensive.
The 2nd approach is better, although there's probably a best case that lies somewhere between them. The 2nd approach here allows multiple applications (or users of the same application) to modify the data at the same time, as the 1st approach may end up using old data if you load all the data at once (especially if a user leaves the application on a while). I would go with the 2nd approach and then figure out what optimizations to make.
Since you think the 1st approach may be usable, I'd assume then you don't have too many users who would use the tool at the same time. If that is the case then, perhaps then you don't need to use any optimizations that the 1st method itself would give you as there's not going to be too much database usage.
When you say you working with ResultSets more often in the 2nd approach than the 1st, well it doesn't need to be that way. You can use the same methods from the 1st approach which translates your data into Java data structures to be used in the 2nd approach.
You already made a very bad decision here:
And when user wants to save new article he chooses the company for this article
from the _list_ of all companies
A list works only reasonably if the number of choices is fairly limited; below 10-20 you may get away with a combo box. For thousands of choices a list is very cumbersome, and the further it grows the slower and more unwieldly chosing from a list becomes.
This is typically solved by some kind of search field (e.g. user types customer number, presses tab and information is fetched), possibly combined with a search dialog (with more search options and a way to select a result found as "it").
Since you will typically be selecting only a few items with a search request, directly quering the DB is usually practical. For a search dialog you may need to artificially limit the number of results (using specific SQL clauses for paging).
Lets say I wanted a web page that would represent a zoo. There should be a list of enclosures (about a ten thousand of them) and it should be possible to display it in three ways:
all enclosures,
only enclosures that the currently logged in user has marked as favorite,
only enclosures that the currently logged in user has commented on.
In all of these cases the list could be too long to fit on a single page and therefore should be divided into multiple pages with a pagination bar.
In order to ease searching for a particular enclosure, all three modes should support additional filtering by a keyword (full-text search in enclosure names). I.e. the user should be able to e.g. display all enclosures marked as favorite that contain a given string in their names. Of course, the list can still be to large and pagination would be applicable here as well.
The question is - how to design the DAO layer to avoid code dupplication and spaghetti code full of conditions? Also, it would be fine to have the code divided into layers/areas of abstraction, so that e.g. the code for building the final SQL queries would not be scattered inconsistently across many different classes from different abstraction layers.
Assuming a traditional request/response web application style here is a sketch:
Represent the various filtering options as classes in supporting code for your DAO. Have the web client specify URL parameters representing the filtering options. You'll need a way to ensure that the filtering options are always sent in on each request, or store them on the user's session.
Map the filtering parameters to the filtering options and pass the options to your DAO. In your DAO's queries "expand" the filtering options into appropriate where claus(es) against the database.
For paging, have the concept of a paging "window". For example, you could have a class that represents the starting row and how many rows to return. Again, expand that class into a predicate executed against the database.
There are other ways to accomplish this (perhaps with one of the million frameworks that are around), but this is how I'd approach it if I had to develop it all from scratch.
Editing my original answer since I misread your criteria. Your DAO will be the same as any other basic DAO. It will (essentially) have a GET method for each of the three queries. If the user wants to narrow down the criteria after that, I would suggest using a jquery plugin like DataTables., assuming the amount of data that gets returned in the DAO methods isn't some outrageously huge amount. That plugin will allow you to add filters to each column that updates as you type, and also has sort, search, and paginate functionality.
I have web application based on jsp and spring mvc where i need resolve this task :
The user must be able to add new instances of the main entity using wizard dialog. The wizard consists of 3 steps:
On the first step there must be a form which allows filling main entity’s fields, including association with the entity related as many-to one (it’s recommended to use drop-down field). The form should contain fields of different types: text, number, date, radio button, etc. Some fields should be required and some are not.
Example: input name, surname, birth date, phone, number of kids, select gender (radiobutton), department (drop-down), etc.
On the second step user fills additional attributes, including association with the entity related as many-to-many with the current one.
Example: associate employee with skills that (s)he has (checkboxes), add some note (textarea).
On the third step all the fields from previous 2 steps should be displayed as read-only fields. The user should confirm saving this data into database. After the user confirms saving, the data should be saved into database, and user should be redirected to the page with the list of objects.
How can i transfer and hold information without using sessions(Http session, session scope)?
You need to keep state across multiple server interactions. There are several possibilities, in general factors such as the size of the state data to be retained influence our decisions.
It sounds like you have some small number of hundreds of bytes here, so you're not particularly constrained by size - a few Megabytes would be more of a challenge.
First possibility, keep it all in the browser in JavaScript variables, no actual need to send anything to server. This is typical of a modern dynamic Web UI, where the server serves up data rather than pages. Sounds like you're in a multi-page world so discount this option.
Second, just put some data (possibly encrypted, in a cookie) effectively the browser is keeping the data for you, but it's shared across the pages.
Third use Http Session state - you case does sound very much like a typical candidate for a session. Why do you want to avoid it? Depending upon your server's capabilities this approach may not give great resilience behaviour (if the state is on one server instance then all requests for a session must be served by the same server). Note that HTTP Session and EJB Session Beans are not the same thing, HttpSessions are lighter weight.
Use a custom session "database" - maybe literally a SQL database maybe something lighter. For larger scale data entry cases, where a user may take 10s of minutes to complete many pages this may be the best option - the user's work is saved should they need to break off and resume later. It's more development work and you need to look at housekeeping too, but it's sometimes the best option.
In summary: be very clear why you reject the "obvious" HTTP session technique, in terms of simplicity it's where I'd start.
I am busy practicing on designing a simple todo list webapp whereby a user can authenticate into the app and save todo list items. The user is also only able to to view/edit the todo list items that they added.
This seems to be a general feature (authenticated user only views their own data) in most web applications (or applications in general).
To me what is important is having knowledge of the different options for accomplishing this. What I would like to achieve is a solution that can handle lots of users' data effectively. At the moment I am doing this using a Relational Database, but noSQL answers would be useful to me as well.
The following ideas came to mind:
Add a user_id column each time this "feature" is needed.
Add an association table (in the example above a user_todo_list_item table) that associates the data.
Design in such a way that you have a table per user per "feature" ... so you would have a todolist_userABC table. It's an option but I do not like it much since a thousand user's means a thousand tables?!
Add row level security to the specific "feature". I am not familiar on how this works but it seems to be a valid option. I am also not sure whether this is database vendor specific.
Of my choices I went with the user_id column on the todolist_item table. Although it can do the job, I feel that a user_id column might be problematic when reading data if the data within the table gets large enough. One could add an index I guess but I am not sure of the index's effectiveness.
What I don't like about it is that I need to have a user_id for every table where I desire this type of feature which doesn't seem correct to me? It also seems that when I implement the database layer I would have to add this to my queries for every feature (unless I use some AOP)?
I had a look around (How does Trello store data in MongoDB? (Collection per board?)), but it does not speak about the techniques regarding user_id columns or things like that. I also tried reading about this in some security frameworks (Spring Security to be specific) but it seems that it only goes into privileges/permissions on a table level and not a row level?
So the question is whether my choice was appropriate and if there are better techniques to do this?
Your choice is the natural thing to do.
The table-per-user is a non-starter (anything that modifies the database structure in response to user action is usually suspect).
Row-level security isn't really an option for webapps - it requires each user session to have a separate, persistent connection to the database, which is rarely practical. And yes, it is vendor-specific.
How you index your tables depends entirely on your usage patterns and types of queries you want to run. Is 'show all TODOs for a user' a query you want to support (seems like it would be)? Then and index on the user id is obviously needed.
Why does having a user_id column seem wrong to you? If you want to restrict access by user, you need to be able to identify which user the record belongs to. Doesn't actually mean that every table needs it - for example, if one record composes another (say, your TODOs have 'steps', each step belongs to a single TODO), only the root of the object graph needs the user id.