How to access different database based on different user in Spring Data Mongodb environment? - spring

In my current implementation, MongoDB architecture looks like
DB : schoola
Collections :
1. students
2. users
DB : schoolb
Collections :
1. students
2. users
And in each instance of Spring Server properties file I do -
SPRING_DATA_MONGODB_DATABASE: <dbname>
SPRING_DATA_MONGODB_URI: <URI to <dbname>>
Clearly this isn't scalable and I am already tired of maintaining different server instances.
Instead what I am looking for I will have a User DB
DB : user
Collections :
1. users (with fields {userName, password, associatedWith: <DB NAME OF THE SCHOOL USER IS ASSOCIATED WITH>)
So how do I do the following?
When the user tries to login in I try validate with user/users and if success I fetch the associatedWith value.
Then I connect to that DB and provide services to that user, again I don't to connect to mongodb with every Rest call, probably I need to maintain a userContext in memory.

One way of doing this would be to provide your own flavour of a MongoDatabaseFactory, that on getMongoDatabase(), reads the tenant from a context source and returns the MongoDatabase to use.
This sample is a bit dated but gives an impression of the overall direction here.

Related

How to manage store "created by" in micro-service?

I am building the inventory service, all tables keep track the owner of each record in column createdBy which store the user id.
The problem is this service does not hold the user info, so it cannot map the id to username which is required for FE to display data.
Calling user service to map the username and userid for each request does not make sense in term of decouple and performance. Because 1 request can ask for maximum 100 records. If I store the username instead of ID, there will be problem when user change their username.
Is there any better way or pattern to solve this problem?
I'd extend the info with the data needed with from the user service.
User name is a slow changing dimension so for most of the time the data is correct (i.e. "safe to cache")
Now we get to what to do when user info changes - this is, of course, a business decision. In some places it makes sense to keep the original info (for example what happens when the user is deleted - do we still want to keep the original user name (and whatever other info) that created the item). If this is not the case, you can use several strategies - you can have a daily (or whatever period) job to go and refresh the users info from the user service for all users used in the inventory, you can publish a daily summary of changes from the user service and have the inventory subscribe to that, you can publish changes as they happen and subscribe to that etc. - depending on the requirement for freshness. The technology to use depends on the strategy..
In my option what you have done so far is correct. Inventory related data should be Inventory Services' responsibility just like user related data should be User Services'.
It is FE's responsibility to fetch the relevant user details from User Service that are required to populate the UI (Remember, call backend for each user is not acceptable at all. Bulk search is more suitable).
What you can do is when you fetch inventory data from Inventory Service, you can publish a message to User Service to notify that "inventory related data was fetched for these users. So there is a possibility to fetch user related data for these users. Therefore you better cache them."
PS - I'm not an expert in microservices architecture. Please add any counter arguments if you have any.*

commuicate ' User' model between two microservices

hello everyone i'm new to microservice's architecture ,
so i have a miscroservice which every entity is linked to the 'user' entity , but the problem is that the
'user' entity is in another microservice , is there any solution ?
I don't know where to user the #onetomany relation if i don't have the two entities in the same microservice)
i can't combine the two microservices together.
what about domain model layer ? is it the best solution to user another microservice's data ?
thanks in advance.
Cant you pass it as a secure jwt token which contains users data so its accessible in other micro service? Another approach is store it as a thread local object.
First answering your questions
1 - I don't know where to user the #onetomany relation if i don't have the two entities in the same microservice)
2 - i can't combine the two microservices together.
--> you can combine 2 services into one (provided considering the load of service)
If the load on your service is big - then
You can utilize something like shared database service for multiple microservices
Go through this blog - it talks about few patterns you can utilize.
http://microservices.io/patterns/data/database-per-service.html.
Also go through this question, it will give you some more undersntading
Microservices: how to handle foreign key relationships

unable to get values from PER_ASSIGNMENT_SECURED_LIST_V table?

I am working in oracle hcm fusion application. Writing a extract rule for a batch loader fast formula. in one of the extract rule formula i am using a DBI PER_HIST_ASG_ASSIGNMENT_NUMBER but it returning 0, that is no values in DBI. The problem is the DBI internally refer a secured view PER_ASSIGNMENT_SECURED_LIST_V. If I query this table from BI publisher I am not getting any rows. Some one suggest that Data role is missing. Can anyone tell me what is the exact datarole that I should add to acces the values from that DBI.
This View is based on security profile added in the Employment like BU,Department,Location etc.
So you try to retrieve the records from a Super User or Implementation user which is not attached any security profile, You will get the results.
Data roles are configured differently for each organization that is using the Cloud.
So you have to check with your application security consultant for the exact data role you need for this table.

Java webapp API id-based security filter

We're building our API and looking for an organized way to grant users access based on what role and permission they have.
From the starting point, we have 3 roles
Admin: can get and edit everything in his organization
Team Admin: can get and edit only his team info and users' info
User: can get any edit his own information
Entity
Team
User
For Security Filters:
We're using JAX-RS with Security Roles and #RoleAllowed to filter access to resources
Id-based filter by if / then / else function. Example with a team admin access to a user.
function isAllowAccess(teamAdminId, userId) {
allowedUserIdsList = queryfor(teamAdminId);
if (userId in allowedUserIdsList) then ... else BAD_REQUEST
}
This code is growing with the increase complexity of multiple roles and many entities. So my questions:
What will be the best way to have an organized id-based filter, is there reputable library for this?
Should we maintain a separate table containing accessible ids of each
entity for each team_admin_id? Then every row updated or inserted will trigger the update of this table.
Is there a formal or widely acceptable method to reduce database
call overhead in each call just to check if the team_admin is
allowed to access a particular user?

How to do POST on a dependent Entity without a backing Repository

I find mentions in lot of answers to Spring Data Rest design related questions to "Aggregate Root" and "Entity" together with "Value Objects".
And I think Repository equate to Aggregate Root.
CASE 1
My question is around this , say there are 2 Entities - User and UserSettings , represented in database as 2 tables and UserSettings having a foreign key user_id pointing to User.
In this case, i would like to do GET/POST on both User as well as UserSettings. From some posts, i found out that repositories should be at aggregate root level which would mean in this case exposing repository for only User since UserSettings depends on User completely.
Right now, i have 2 repositories with bidirectional relationships , one for each i.e UserRepository and UserSettingsRepostory , both exposed as REST services.
As a result, I do POST on UserSettings and User as
/app/userSettings
/app/users
For, GET I use for UserSettings & User -
/app/users/{id}/userSettings
/app/users/{id}
If I don't expose UserSettingsRepository , what will be equivalent to POST on /app/userSettings, where I am currently doing as below -
Method - POST
Input JSON - {
"user" - "/app/users/{id}",
..
}
CASE 2
Likewise if there are following Entities/Tables - User, UserPost and UserComment - here UserComment has 2 foreign keys as UserPost as well as User.
I suppose here we have 2 aggregate roots and therefore should have 2 repositories as UserRepository and UserPostRepository.
Another way of thinking about is that since all are after all dependent on user and so we can just have 1 repository for UserRepository only.
Here too, contrary to my current state where I have even UserCommentRepository, I am not sure how to do POST on UserComment once remove that.
If you you want to interact with UserSettings individually, they need to become dedicated resources, which means they're not part of the User aggregate anymore. An aggregate makes sure certain assertions are held within itself by making sure, nobody else manipulates the state of parts of it. So if you want do the latter, the aggregate is not an aggregate anymore. Spring Data REST just exposes these concepts on an HTTP level.
To keep User and UserSettings together you basically have two options:
Introduce a dedicated state transition for the user resource by adding a link. Define the supported HTTP verbs and data structure for that resource pointed to.
Use an HTTP PATCH operation on the user resource to manipulate parts of the resource.

Resources