How to implement sharing ability in a Spring web app? - java

Kind of a higher level question here.I've got a web application that is fairly simple. There are three seperate "objects" in the application. A Filter, an Authorization, and a Job. Each Job has to have a Filter and an Authorization to run.
Now a user of this application can create any of these objects and they are all linked to that specific user. Now however, the requirements state that they'd like to implement sharing. So a user can share their created items with other users. Honestly I'm just not sure of the best method to implement such a feature and am hoping someone can provide some ideas.
In the DB, each record has a user column that identifies the user who created it. I initially thought of adding a shareUser column, but that wouldn't really work since each record could be shared with multiple users. I'm just not sure the best way to tie these all together. Do I need an entirely new table in the DB that link's users to shared records?
Any thoughts on this would be appreciated. Thank you.

Yes, you do need a new table for each type of record you need to be "owned". You should use cross reference tables for this case.
something like:
userFilter
- userId
- filterId
If a user can only share a record they exist, you should have a createdByUserId column on the particular table.

Related

Optimal way of storing current user data over multiple classes

I have a login page which connects to a Database, the Database has only one client, when a user logs on he/she may make certain changes to his profile and then save. A large number of frames require the current user id in order to manipulate his data
Among the possible ways of storing the user currently logged in is
1) to save the data to a temporary text file and persist it before the user logs out
2) another option would be to use variables across all the frames ,however I'm not too confident about this
3) a third way would be to have a Boolean column in the database and to persist the the data of the field with true in it
Perhaps there are better ways of storing the current user Id could somebody elucidate other possible methods and highlight the pros and cons of each implementation with reference to an "optimal" method of doing this
Edit: This is a desktop application
I would suggest not to share this information in any static context for the reason it will render your project as very hard to test once it gets big enough. See this link for more info: When to use singletons, or What is so bad about singletons?
What I would do is store session objects in some map, identifying the appropriate session by an ID that will be given and sent back to you via client cookie. This is how the web has been doing it for years, and it is still doing it this way. Simply pass the session object around to any class that requires access to that data when it needs it.
If you are using a J2EE implementation, then you may already have support for sessions within that implementation, you should check out "How to Use Sessions"
This is more of a software design question, and covering the basis to complete the patterns used to support what I just suggested is unfortunately beyond the scope of the question
The logged user is an instance of the class Person or LoggedUser.
You have to instantiate it and share its reference between Views via a Model.

Tables in Spring security

I want group based security in my application. However I don't understand how to use it.
Looking at the two different database schemas from the appendix, I got some questions. Am I supposed to extend the group_members table with password, enabled, first name etc? Or am I supposed to have another table named for instance user which hold this info? If I need, why do I need the group_member table?
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/appendix-schema.html
It is not compulsory to use group table. you can also use single or two table for authentication. Refer the following link for reference.
http://www.mkyong.com/spring-security/spring-security-form-login-using-database/

how to integrate Java security layer (Apache Shiro|Spring Security) to webapp menu system

As the title says, i have a need to create a dynamic menu stored as a tree in the database and there are plans to put an interface on it.Now i need to decide how to implement the Access Control Layer based on what is on the market suitable for this requirement.
I heavily use Spring IoC, spring mvc etc....with hibernate for my project. I've used apache shiro before and it's not bad.just that the community is still young so it takes time for a question regarding shiro to have contributions and there is not extensive documentation.
I was still planing on using shiro anyway because i've an experience which i don't have with spring security.Now the first question should have been Is is a good idea to tie ACL to menu system|navigation system .I would be please if anyone could share his experience regarding that.
So on top of my head i have this model in mind users, roles, rights, users_rights ,roles_users, roles_rights
users //contains creds and user detail
roles //contains roles
rights // contains rights (including menu entries matching rights, if i have to tie them)
roles_users //many-to-many roles-users with extra columns mapped as entity
roles_rights // many-to-many roles-rights with extra columns mapped as entity
users_rights //many-to-many users-rights mapped as entity with extra columns. special rights for user and overwrite the overall rights given by roles. can deny rights given by a role or add rights not inside any roles
so in the rights table i could have like:
id
name // in the form of admin:users:list
description
menu_name // unique name what shows on page
menu_url
the only question is that how do i handle submenu? self many-to-many rights-rights?
at the end it all becomes so complex.So i would like have other perspective, insights ,suggestions. thanks
I hope I understood what you want.
I think that using a self foreign key is valid.
However, I would suggest that you compute the "ACL value" of a sub menu upon its creation, or upon update of one of the parents,
So you won't spent time calculating it while during ACL check for the sub menu.
I'm sorry if I didn't use the terms correctly,
What in general I mean is that if you have some value at a tree, and this value might be dependent on the value of the parent node in the tree,
you should consider to calculate the value for the child node/leaf during insertion , update, or any change at one of the ancestors.

Securing a Multi tenant SaaS application

I'm multing a multi-tenant SaaS web-application in Java, Spring, Struts2 and Hibernate. After a bit of research, i choose to implement multi-tenancy in a shared db, shared schema, shared table approach. And tagging each db-line with a tenantId.
I have rewritting my application, so Managers and Dao's will take the tenantId as a parameter to only serve the correct db-resources.
This works perfect for all view's when getting information. And also for creating new stuff (using the logged in users tenantId to store the info).
However, for updating and deleting stuff I am not sure how to secure my application.
For example: When a user want to edit an object, the url will be: /edit?objectId=x
And this is mapped to an action that will retrieve this object by Id. Meaning any logged in user can by url-modification view any object.
This i can solve by adding the tenantId to the Dao so if the User tries to view an object outside his tenancy he will get nothing.
Ok thats ok then, but about when sending in the edit-form?
What if the user modifies the request, messing with the hidden field objectId so the action will receive a request to alter an object not belonging to the users tenancy.
Or if the users url-modifies a delete action /delete?objectId=x
Basicly I need some way of assure that the logged in user has access to whatever he is trying to do. For all get's its easy. Just putting the tenantId in the where clause.
But for updates and deletes i'm not sure what direction to go.
I could query the db for every update and delete to see if the users has access to the object, but i'm trying to keep db-interaction to the minimum. So i find it impractical to make an extra db-call for every such action.
Does anyone have any hints or tips to my issues?
The same for reading applies to writing/updating: user can only see/access/change what they own. Your question is more about database that about anything else. The same constraints you apply to viewing data must also apply to writing data.
In this case, you don't want to wear the performance of a query first then an update. That's fine, since you can update the database with conditions. Since this seems likely to be database-level in your case you need to know what your database is capable of (to do it in one go). For example, oracle has the merge statement.
I am quite late to this thread and maybe you have already built the solution you were asking here about. Anyway, I have implemented a database-per-tenant multitenant web application using Spring Boot 2 and secured the web access using Spring Security 5. The data access is via Spring JPA (with Hibernate 5 as the JPA provider). Do take a look here.

How to maintain/generate tables in Hibernate for multi-user purpose?

I'm working on a project using Play Framework that requires me to create a multi-user application. I've a central panel where we add a certain workshop for a team. Thing is, I don't know if this is the best way, but I want to generate the tables like
team1_tablename
team1_secondtable..
Then when a certain request hits using the virtual host (e.x. http://teamawesome.workshop.com) I would need to maneuver the query to THAT certain table.
The problem is not generating the tables, but working with the models. All the workshops are going to have the same generic tables. In the model I would have to state the table, etc but then if this was PHP with doctrine I would have a template created them after creating the workshop team1, but in java even if I generate them I would have to compile them too which requires me to do more research.
My question is more Hibernate oriented before jumping the gun here and giving up on possible solutions. I'm all ears
I've thought of using NamedQueries, I don't know if I misread but I read in a hibernate book that you could query then add the result to a generic model so then I use that model to retain all my results...
If there are any doubts let me know, thanks (note this is not a multi database question, just using different sets of tables with unique prefixes)
I wonder if you could use one single set of tables, but have something like TEAM_ID as a foreign key in each table.
You would need one single TEAM table, where TEAM_ID will be the primary key. This will get migrated to tables and become part of foreign keys.
For instance, if you have a Player entity, having a collection of HighScores, then in the DB the Player table will have a TEAM_ID (foreign key from the Team table) and the HighScores table will have a composed foreign key (Player_id, Team_id) coming from the Player table..
So, bottom line, I am suggesting a logical partitioning of your database rather then a physical one (as you've considered initially).
Hope this makes sense, it definitely needs more thought, but if you think it's an interesting idea, I can think it through in more detail.
I am familiar with Hibernate and another web framework, here is how I would handle it:
I would create a single set of tables for one team that would address all my needs. Then I would:
Using DB2: Create a schema for each team copying the set of tables into each schema.
Using MySQL: Create a new Database for each copying the set of tables into each one.
Note: A 'database' in MySQL is more like a schema in other databases. (Sorry I'd rather keep things too simple than miss the point)
Now you can set up a separate hibernate.cfg.xml file for each connection (this isn't exactly the best way but perhaps best to start because it's so easy). Now you can specify the connection parameters... including the schema/db. Now your entity table, lets say it's called "team" will use the "team" table where ever it is connected...
To get started very quickly, when a user logs on create a user object in their session.
The user object will have a Hibernate SessionFactory which will be used for all database requests built from the correct hibernate.cfg.xml file as determined by parsing the URL used in the login.
Once the above is working... There are some serious efficiency concerns to address. That being that each logged on user is creating a SessionFactory... Maybe it isn't an issue if there isn't a lot of concurrent use but you probably want to look into Spring at that point and use a connection pool per team. This way there is one Session factory per team and there is no major object creation when a user signs in.
The benefits of this solution is that it should be easier to create new sets of tables because each table set lives in it's own world. There will only be one set of Entity Classes as opposed to the product of one for every team and table. The database schema stays rather simple not being complicated by adding team names and then the required constraints. If the teams require data ownership and privacy it will be rather easy to move the database to a different location.
The down side is that if the model needs to be changed for a team it must be done for each team (as opposed to a single table set using teamName as a foreign key).
The idea of using different tables for each team (despite what successful apps may use it) is honestly quite naïve, and has serious pitfalls when you take maintenance into account...
Just think what you will be forced to do if you discover you need a new table or even just an index... you'll end up needing to write DML scripts as templates and to use some (custom) software to run them on all the teams...
As mentioned in the other answers (Quaternion's and Octav's), I think you have two viable options:
Bring the "team" into your data model
Split the data in different databases/schemas
To choose the option that works best for you, you must decide if the "team" is really something you can partition your dataset into, or if it is really one more entity you want to bring into your datamodel.
You may have noticed that I'm using "splitting" here instead of "partitioning" - that's because the latter term is generally used by DBAs to indicate what we could call "sharding" - "splitting" is intended to be a stronger term.
Splitting is only viable if:
entities in different partitions do not ever need to reference each other
no query will ever need to access data from different partitions (this applies to queries used for reporting too)
As you might well see, splitting in this sense is not very attractive (maybe it could be ok now, but what when you find yourself wanting to add new features?), so my advice is to go for the "the Team is an entity" solution.
Also note that maintaining a set of databases/schemas is actually harder than maintaining a single (albeit maybe a bit more complex) database... again, think of what steps you should take to add an index in a production system...
The only downside of the single-databse solution manifests if you end up having multiple front-ends (maybe due to customizations for particular customers): changes to a shared database have the potential to affect all the applications using it, so you may need to coordinate upgrades to the different webapps to minimize risks (note, however, that in most cases you'll be able to change the database without breaking compatibility).
After all it's a little bit frustrating to get no information just shoot into the dark. Nevertheless now I have start the work, I try to finish.
I think you could do you job with following solution:
Wrote a PlayPlugin and make sure you add to every request the team to the request args. Then you wrote your own NamingStrategy. In the NamingStrategy you could read the request.args and put the team into your table name. Depending on how you add it Team_ or Team. it will be your preferred solution or something with schema. It sounds that you have an db-schema so it would be probably the best solution to stay with this tables and don't migrate.
Please make the next time your request more abstract so that you can provide some information like how many tables, is team an entity and how much records a table has (max, avg, min). How stable is your table model? This are all questions which helps to give a clear recommendation with arguments.
You can try the module vhost, but it seems not very good maintained. But I think the idea to put the name of the team into the table name is really weired. Postgres and Oracle has schemas for that. So you use myTeam.myTable. But then you must do the persistence by your selves.
Another approach would be different databases, but again you don't have good support by play. I would try this
Run for each team a separate play-server, if you don't have to much teams.
Put a reference to a Team-table for every model. Then you can use hibernate-filters or add it manually as additional parameter to each query. Of course this increase your performance. You can fix this issue with oracle partitions.

Categories