PostgreSQL adding multiple results to an array - arrays

Hello Stack Overflow Users,
I'm trying to pull together a list of users and all of their permissions, but I want to aggregate the permissions so they they list in the single record of the user.
The users table is pretty simple, but the permissions are broken out individually.
To give you an example, there are 3 tables: users, user_access, page
Also, I'm stuck with PostgreSQL v8.4.
The data pretty much looks like the following:
users table
user_id,username
1,bob
2,cindy
3,jen
user_access table
id,user_id,page_id,allowed
1,1,5,true
2,1,7,true
3,1,8,false
4,2,4,true
5,2,5,true
6,2,7,false
7,3,1,true
8,3,5,false
page table
page_id,page_name
1,report_1
2,report_2
3,report_3
4,admin
5,users
6,options
7,addl_options
8,advanced
So far I have been able to create an array for the permissions, but I'm only grabbing a single page permission and displaying the result of whether it's allowed or not. I'm having a hard time figuring out how to collect the rest of the pages and what they're set to within the one cell for each user.
What I have so far:
select users.user_id, users.username,
(select array(select page.page_name || ':' || user_access.allowed)
where users.user_id = user_access.user_id and page.page_id = user_access.page_id) as permissions
from users
full join user_access on users.user_id = user_access.user_id
full join page on page.page_id = user_access.page_id;
But this only returns results like the following:
user_id,username,permissions
1,bob,{report_1:<null>}
1,bob,{report_2:<null>}
1,bob,{report_3:<null>}
1,bob,{admin:<null>}
1,bob,{users:true}
1,bob,{options:<null>}
1,bob,{addl_options:true}
1,bob,{advanced:false}
What I want to get back instead is all permissions per user record like this:
user_id,username,permissions (where permissions is an array of <page_name>:<allowed>)
1,bob,{report_1:<null>,report_2:<null>,report_3:<null>,admin:<null>,users:true,options:<null>,addl_options:true,advanced:false}
2,cindy,{report_1:<null>,report_2:<null>,report_3:<null>,admin:true,users:true,options:<null>,addl_options:false,advanced:<null>}
3,jen,{report_1:true,report_2:<null>,report_3:<null>,admin:<null>,users:false,options:<null>,addl_options:<null>,advanced:<null>}
I appreciate any advice you could assist with.
Thank you!

You need a cross join between users and page, then an outer join to the permissions. The result of that then needs to be grouped:
select u.user_id, array_agg(concat(p.page_name, ':', coalesce(ua.allowed::text, '<null>')) order by p.page_name)
from users u
cross join page p
left join user_access ua on ua.page_id = p.page_id and ua.user_id = u.user_id
group by u.user_id;
Online example: https://rextester.com/XYC99067
(In the online example I used string_agg() instead of array_agg() as rextester doesn't display arrays nicely)

Related

LEFT join on secure view fails in snowflake

I have a normal view and one secure view and a table.
create or replace NORMALVIEW as select click_id FROM SECURE_VIEW a
LEFT JOIN
TABLE e
ON (e.click_id = a.google_click_id);
select * from NORMALVIEW;
I am getting the error:
SQL execution internal error: Processing aborted due to error 300002:2523989150; incident 8846932.
other operations such as union is working
If you got an incident then you will need to open a case with Snowflake support to understand what is happening.
So I assume the SELECT part is valid:
select e.click_id
FROM SECURE_VIEW a
LEFT JOIN TABLE e
ON (e.click_id = a.google_click_id);
I also assume the view is actually defined more like:
CREATE table test.test.table_name (click_id int);
insert into test.test.table_name values (0),(1);
CREATE SECURE VIEW test.test.SECURE_VIEW AS
SELECT click_id as google_click_id
FROM test.test.table_name
WHERE click_id%2 = 1;
CREATE VIEW test.test.NORMALVIEW AS
SELECT click_id
FROM test.test.SECURE_VIEW AS a
LEFT JOIN test.test.table_name AS e
ON e.click_id = a.google_click_id;
Or some other all valid stuff, thus those views would not be created. for the select to fail on.
I wonder if you grab the DDL of the view and try recreate then (with different names) if they are still valid, or if the shape of some underlying table changed, or if something as be drop/recreate/renamed..
SELECT * from NORMALVIEW;
But yes, at the point open a support ticket.

how to check groups for specific user in sql server [duplicate]

In the Security/Users folder in my database, I have a bunch of security groups, include "MyApplication Users". I need to check if I am (or another user is) in this group, but I have no idea how to query for it or where I could see this information. I tried looking in the properties, but couldn't find anything. Any ideas?
Checking yourself or the current user:
SELECT IS_MEMBER('[group or role]')
A result of 1 = yes,0 = no, and null = the group or role queried is not valid.
To get a list of the users, try xp_logininfo if extended procs are enabled and the group in question is a windows group :
EXEC master..xp_logininfo
#acctname = '[group]',
#option = 'members'
For a quick view of which groups / roles the current user is a member of;
select
[principal_id]
, [name]
, [type_desc]
, is_member(name) as [is_member]
from [sys].[database_principals]
where [type] in ('R','G')
order by [is_member] desc,[type],[name]
To find the AD Group members in the Instance, we can use below query:
xp_logininfo 'DomainName\AD_GroupName', 'members'
By using this query, we can find the below states.
account name, type, privilege, mapped login name, permission path
Accepted answer from DeanG is the preferred solution for getting this info within SQL Server
You can use Active Directory tools for this. I like Active Directory Users and Computers that is part of the Remote Server Administration Tools. Follow the link to download and install the tools on Windows 7.
Once installed, you can search for a specific group name:
Then you can see group membership using the Members tab:
If you don't want to use the AD browser packaged with RSA tools, there are several others available.
You don't.
Instead you use the users and groups to grant/deny privileges, and let the engine enforce them appropiately. Attempting to roll your own security will get you nowhere fast. A banal example is when you will fail to honor the 'one deny trumps all grants' rule. And you will fail to navigate the intricacies of EXECUTE AS. Not to mention security based on module signatures.
For the record: users, roles and groups are exposed in the sys.database_principals catalog view. sys.fn_my_permissions will return the current context permissions on a specific securable.
The code that is provided on the Microsoft page here works for me, every time.
SELECT DP1.name AS DatabaseRoleName,
isnull (DP2.name, 'No members') AS DatabaseUserName
FROM sys.database_role_members AS DRM
RIGHT OUTER JOIN sys.database_principals AS DP1
ON DRM.role_principal_id = DP1.principal_id
LEFT OUTER JOIN sys.database_principals AS DP2
ON DRM.member_principal_id = DP2.principal_id
WHERE DP1.type = 'R'
ORDER BY DP1.name;
Please let me know if this works for you!

SonarQube - SQL Server : get users and groups associated with Project in SonarQube from backend database

I need to find the list of users and group associated with project in SonarQube.
I try to find tables user_roles and group_roles that have a column resource_id. This can be used to get corresponding kee value in table resource_index. This kee value is not same as projects file kee value.
Select *
into #TempTblSnprjusrs
From
(Select
users.login "lanid", users.name "Name", resource_index.kee "Kee"
from
user_roles, resource_index, users
Where
resource_index.resource_id = user_roles.resource_id
and users.id = user_roles.user_id) as x;
But we cannot get corresponding values of kee in projects table.
Select Distinct
#TempTblSnprjusrs.lanid, #TempTblSnprjusrs.Name,
#TempTblSnprjusrs.kee, projects.Name
from
#TempTblSnprjusrs
join
projects on projects.kee = #TempTblSnprjusrs.Project_key;
The database is not an API.
To get the users and groups associated with a project permission-wise, use the Administrative Security interface. Otherwise, you'll want the permissions web services.

Stored Procedure with two input params and multiple matches and create view with in

I am not much strong in SQL, so looking for some help.
First I am looking for suggestion for the best way to implement this logic in SQL and then some sample code to implement.
My portal is going to connect Students and Training Providers.
Students: Select what courses (multiple) they want, type of delivery (online, class room), Industry(domain) to which the course to be targeted more, Location Preference.
Training Providers: Select what courses offering (so one record for each course), offering locations, type of delivery for each course, industries (multiple) it is targeting.
When student login:
I would like to create SP which in turn create view to store the matched records of the Training Providers data which matches that student needs of that StudentID, CourseID passed to SP
I have created the following sp ( but not included create view part as I am not sure how to do this)
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[sp_TPsMatched2StuCourse]
-- Add the parameters for the stored procedure here
#StuID int,
#CourseID int
AS
BEGIN
Select TP.MemID,TP.PastExp,SN.DeliveryType,SN.LocPref,SN.Industry,SC.CourseID from
tbl_TrainingProvider as TP , tbl_StuCourses as SC, tbl_StuNeeds SN
where SN.CourseID = #CourseID and SN.StuID = #StuID and
SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and
SN.Industry IN (TP.Industries)
END
--- exec sp_ELsMatched2EntProp 1, 1
Why I need to put the data is as follows:
Assume the data is stored in that dynamic view and that would be bind to datagrid. Student then select interested TPs. Then only contact details would be shared to each other and this cannot be reveresed. So I would put this interested data in another table later. Every time data changes, hence the matches. Student can change some of his/her needs or new TPs join etc so view to be temparory.
when I executed this using above command, I am not getting data though it matches few records. What is wrong I am doing.
Any help would be greatly appreciated.
You are not getting expected results because you filter out too many records in WHERE( I'm talking about this part : SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and SN.Industry IN (TP.Industries)). I'd recommend to use JOIN ... ON instead of specifying all tables in FROM and join condition in WHERE. I'm not sure what you want exactly, but I believe you are looking for
FROM tbl_StuNeeds SN
LEFT JOIN tbl_TrainingProvider as TP ON (TP.DeliveryMode = SN.DeliveryType AND
SN.LocPref = TP.LocOffering AND TP.Industries = SN.Industry)
WHERE SN.CourseID = #CourseID and SN.StuID = #StuID
Also, there is no join conditions in your code for tbl_StuCourses as SC which results in cross-join.
Finally, why do you need a stored procedure at all? From what I see in your example, a table-valued function will work better:
CREATE FUNCTION [dbo].getTPsMatched2StuCourse(#StuID INT,#CourseID INT)
RETURNS TABLE AS
RETURN
Select .... ;

How to find loginname, database username, or roles of sqlserver domain user who doesn't have their own login?

I have created a login and database user called "MYDOMAIN\Domain Users". I need to find what roles a logged on domain user has but all the calls to get the current user return the domain username eg. "MYDOMAIN\username" not the database username eg. "MYDOMAIN\Domain Users".
For example, this query returns "MYDOMAIN\username"
select original_login(),suser_name(), suser_sname(), system_user, session_user, current_user, user_name()
And this query returns 0
select USER_ID()
I want the username to query database_role_members is there any function that will return it or any other way I can get the current users roles?
I understand that the Domain Users login is mapped into AD group?
You have to bear in mind that user can be in several AD groups and each of them can be mapped somehow in database which may be a bit messy. Also it means you need something with multiple results :)
Try this:
select * from sys.server_principals where type_desc = 'WINDOWS_GROUP' and is_member(name) = 1
I think it should grab properly all Windows Group logins that will be tied with particular users. After that you can join it for database users i.e.:
Select u.name from YourDB.sys.syslogins l
inner join YourDB.sys.sysusers u
on l.sid = u.sid
where l.loginname = ANY (select * from sys.server_principals where type_desc = 'WINDOWS_GROUP' and is_member(name) = 1)
You have to keep in mind that - all the way - you may need to handle whole sets rather then single values.

Resources