Changing DB query for specific user - spring

In our project, we are using spring, JPA & hibernate over Mysql.
I have a DB table that contains permissions per each user. this table has a lot of implications all over the system.
I need to add a "super user" / admin, that has permissions for everything.
I want that every query that made by this admin user - will "simulate" like the permissions table contains permissions to this admin user.
For example:
The DB table is -
entityId | userId
If we have 2 entities, and user#17 has permissions to them, the rows would be
1 | 17
2 | 17
Lets say the admin user is user#20. I don't want to add rows to this table. I want that every access to this table will add "temporary rows".
For example, if I have the following query:
select e from MyEntity e where e.id in (select p.entityId from PermissionEntity p where p.userId = :userId)
I want that if the logged in user is admin user, the query will look like:
select e from MyEntity e where e.id in (select p.entityId from PermissionEntity p)
or
select e from MyEntity e where e.id in (select p.entityId from PermissionEntity p where 1=1 or p.userId = :userId)
Any advice how to implement this?

I suppose you have a central method where you check the rights. If so, simply try:
TypedQuery<MyEntity> query = null;
if (crtUser.getId() != 20) {
query = entityManager.createQuery("select e from MyEntity e where e.id in (select p.entityId from PermissionEntity p p.userId = :userId)", MyEntitiy.class);
}
else {
query = entityManager.createQuery("select e from MyEntity e", MyEntitiy.class);
}
If you don't have a central method for this logic, but have a single method, then you could try the following:
query = entityManager.createQuery("select e from MyEntity e where e.id in (select p.entityId from PermissionEntity p p.userId = :userId) OR :userId=20", MyEntitiy.class);

Related

LINQ to SQL multiple tables left outer join w/condition in 'on' clause

SELECT u.username, COUNT(r.id)
FROM users u
LEFT JOIN userroles ur ON u.id = ur.userid
LEFT JOIN roles r ON ur.roleid = r.id AND r.name = 'Managers'
GROUP BY u.username
ORDER BY u.username
The goal is very simple, the above SQL runs fine, now I need to figure out how to convert it into LINQ code. I have the left joins working, the two things I don't know how to do is the count and the r.name = 'Managers'. Here is what I have so far, how do I finish it off?
var result =
from user in _context.Users
join userRole in _context.UserRoles on user.Id equals userRole.UserId into userUserRoleGroup
from u in userUserRoleGroup.DefaultIfEmpty()
join role in _context.Roles
on u.RoleId equals role.Id into roleUserRoleGroup
from r in roleUserRoleGroup.DefaultIfEmpty()
select new UserRole { Username = user.UserName, RoleName = r.Name };
You can do the count like this:
var count = from role in _context.Role
group role by role.UserId into groupedRoles
select new
{
RoleId = groupedRoles.Key,
Total = groupedRoles.Count()
}
and then you can join the variable "count" in your query.
It will have the property "Total" that is your count.

Convert inner join native query to jpql

I have this method
#Query("select * from feed_tbl feed inner join view_tbl viewers on feed.id <> viewers.feed_id where viewers.user_id = :userId", nativeQuery = true)
fun findAll(#Param("userId") userId: Long): List<Feed>
entities:
User,
Feed
view_tbl is JoinTable in user entity
You should be able to use not in construct:
select f from Feed f where f not in (
select u.feeds from User u where u.id = :userId
)
Of cause you will need to map User to Feed as many-to-many

how to write a Oracle view with this query?

I am using oracle 11g. I want to query with 3 queries.
First one, it is the main. Select to find condition.
Select role, name from tablerole where name is not null and ID=#param1;
This query will return #role with 2 level (admin and user)
The 2 other sub queries will base on this condition.
Up on the first query.
If role='admin' then select*from tablescreen where name is not null and ID=#param1;
If role='user' then select*from tablescreen where name='2';
#param1 is given when I call this view or when I using.
I consider it will be view or function or procedure best for this query.
How to write this query that can accept an input parameter into the query for looping source and return output where matched condition.
Thanks for your kindness.
Nam hmoob.
As far as I understood the question, that would be a view that consists of two select statements:
one that uses condition for admin
another one for user
The first query you posted will be used in a join with the tablescreen table. Something like this:
create or replace view v_role as
-- select for ADMIN
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where s.name is not null
and r.role = 'admin'
union all
-- select for USER
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where s.name = '2'
and r.name = 'user';
Or, as Zynon suggested, without union:
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where ( s.name is not null
and r.role = 'admin'
)
or ( s.name = '2'
and r.name = 'user'
);
You'd then use it as
select * from v_role v where v.id = &param1;

Peewee select with circular dependency

I have two models Room and User. Every user is assigned to exactly one room and one of them is the owner.
DeferredUser = DeferredRelation()
class Room(Model):
owner = ForeignKeyField(DeferredUser)
class User(Model):
sessid = CharField()
room = ForeignKeyField(Room, related_name='users')
DeferredUser.set_model(User)
Now, having sessid of the owner I'd like to select his room and all assigned users. But when I do:
(Room.select(Room, User)
.join(User, on=Room.owner)
.where(User.sessid==sessid)
.switch(Room)
.join(User, on=User.room))
It evaluates to:
SELECT "t1".*, "t2".* # skipped column names
FROM "room" AS t1
INNER JOIN "user" AS t2 ON ("t1"."owner_id" = "t2"."id")
INNER JOIN "user" AS t2 ON ("t1"."id" = "t2"."room_id")
WHERE ("t2"."sessid" = ?) [<sessid>]
and throws peewee.OperationalError: ambiguous column name: t2.id as t2 is defined twice.
What I actually need to do is:
room = (Room.select(Room)
.join(User.sessid=sessid)
.get())
users = room.users.execute()
But this is N+1 query and I'd like to resolve it in a single query like:
SELECT t1.*, t3.* FROM room AS t1
INNER JOIN user AS t2 ON t1.owner_id = t2.id
INNER JOIN user as t3 ON t3.room_id = t1.id
WHERE t2.sessid = ?;
Is there a peewee way of doing this or I need to enter this SQL query by hand?
You need to use a model alias when you are using the same table in two different contexts. So:
Owner = User.alias() # Create a model alias.
(Room.select(Room, Owner, User)
.join(Owner, on=(Room.owner == Owner.id))
.where(Owner.sessid == sessid)
.switch(Room)
.join(User, on=User.room))
http://docs.peewee-orm.com/en/latest/peewee/api.html?#Model.alias

Join statement in Linq to Sql

I need to write Join statment after writing query in linq
example :
var Query = (from Tab in Db.Employees
select Tab)
as i have some cases to perform join operation so
i need to do it on this Query Query.Join(Join with another Table like Department); I need the Syntax
if (DeptID != -1){ Query.Join(Join with table Department where FkDeptID = DeptID); }
Consider the usage of join in the LINQ 'query syntax':
from t1 in db.Table1
join t2 in db.Table2 on t1.field equals t2.field
select new { t1.field2, t2.field3}
Something like this?
var results = (from q in Query
join m in myList on q.SomeID = m.SomeID
select unknown);
Try using this query:
var Query =
from e in Db.Employees
join d in Db.Departments on e.FkDeptID equals d.DeptID into departments
select new
{
Employee = e,
Department = departments.SingleOrDefault(),
};
This works assuming that when e.FkDeptID == -1 that there is no record in the Departments table and in that case Department would be assigned null.
You should never have more than one department for an employee so I've used SingleOrDefault rather than FirstOrDefault.

Resources