Row-level-security based on relation table data - postgresql

I am getting into Supabase and to practice I am making a suuuper simplified website-builder.
However I am having troubles with the row-level-security policies.
I have three tables:
user → with users' information like first name, last name, etc.
website → all websites
user_website → Contains the information which website belongs to which person (since a website can be owned/editted by multiple users)
user
user_id
...
website
website_id
...
user_website
user_id
website_id
user_role
...
I didn't find any useful resource, because honestly I still lack the knowledge to know how to search properly for what I need.
I only found simple expressions like (uid() = user_id), but since the "permissions" are stored in another table, I don't know how to access that.
I used queries like the following but it didn't work as intended:
SELECT
*
FROM
user_website as uw
JOIN website as w
ON uw.website_id = w.website_id
WHERE
uw.user_id = auth.uid()
Help is much appreciated – thanks!

You could define a policy like that:
CREATE POLICY may_edit ON website
FOR UPDATE TO PUBLIC
USING (EXISTS
(SELECT 1 FROM user_website
WHERE user_website.website_id = website.website_id
AND user_website.user_id = uid()
)
);
Here, uid() is a function that returns your current user ID.
This policy will let everyone modify their own website.

I called a friend for help and he pointed out a section in the Supabase docs about "policies with joins" ... yet it still didn't work for me.
The reason was that the RLS-policy on the table website references the table user-website, which didn't allow users yet to access anything.
Solution
RLS-policy for select on website:
auth.uid() in (
select user_id from user_website
where website_id = website.website_id
)
RLS-policy for select on user-website:
auth.uid() = user_id

Related

TYPO3: How to display Frontendgroup memberships in backend, felogin Extension

I have a TYPO3 v10 instance. The felogin Extension is installed to manage 4000 users in 100 usergroups, lots of tiny projects.
Is there a feature, a trick, an extension to answer this question, while working in the backend:
For a given frontenduser-group what are the feusers that belong to that group?
There does not seem to be a way to display this in the backend. At least not in the "List" module, after clicking on any frontendgroup-name, then working in any of the standard tabs "
General / Options / Access / Notes / Extended"
Right now I get along with SQL statements like
SELECT * FROM fe_users WHERE usergroup like '%261%';
but this is very inconvenient.
I have migrated the users and groups from one old TYPO3 instance to a newer one, and now I want to enable editors to cross-check and review group memberships themselves.
The Stackoverflow "Similar questions" text-analysis tool points out that my question is indeed similar to this one: Extbase fe_user findByUsergroup - but that question is 4 Years old, and perhaps there has been some progress?
I know of such "included" feature. The listview offers a "ref" (references) column which shows you all references to this group. this might help a bit. but contains pages, content elements... and user records in a mix.
Another option is the export a CSV of the website users with the "Groups, column enabled. This should give them all the data to review the group memberships.
If that is not enough, I would create an custom module to create such a view.
Meanwhile, as a workaround, I have used a nonstandard-SQL feature, the group_concat() function, to copy all frontendusernames of each group into the (empty) "description" field of the fe_groups table.
There they form a comma-separated list. A screenshot illustrates what my backend panel now looks like. See first line:
This method is only feasible of you are running a one-off migration, or if you can practice on a staging server first. You need to have absolute control over the TYPO3 database, and your bosses and editors shouldn't mind and like the final result. Also it overwrites what is in the description column.
Also, frontendusers who are in two or more groups will NOT get added to the csv-lists! Because their usergroupcolumn has values like 262,398 which cannot be INNER JOINed properly with fe_group.uid.
The key benefit of the group_concat() method is that a single SQL UPDATE statement (almost) solves the problem. No custom PHP programming needed.
/* works on mariadb:10.3 */
UPDATE
fe_groups g,
(
SELECT
usergroup,
GROUP_CONCAT(
u.username
ORDER BY
username SEPARATOR ', '
) AS 'usernames'
from
fe_users u
where
usergroup not like '%,%'
group by
usergroup
) AS user_lookup
SET
g.description = user_lookup.usernames
WHERE
user_lookup.usergroup = g.uid
and user_lookup.usergroup not like '%,%';
The code above does not work on mysql 5.7. There I had to try this instead:
/* works on mysql 5-7 */
SET
session group_concat_max_len = 15000;
create temporary table fe_groups_extrainfo
SELECT
usergroup,
GROUP_CONCAT(
u.username
ORDER BY
username SEPARATOR ', '
) AS 'usernames'
from
fe_users u
where
usergroup not like '%,% and uid > 9'
group by
usergroup
limit
0;
insert into
fe_groups_extrainfo
SELECT
usergroup,
GROUP_CONCAT(
u.username
ORDER BY
username SEPARATOR ', '
) AS 'usernames'
from
fe_users u
where
usergroup not like '%,%'
group by
usergroup;
update
fe_groups g
inner join fe_groups_extrainfo x on g.uid = x.usergroup
set
g.description = x.usernames;
Sorry it is not a single SQL Statement as the mariadb-SQL statement but still simpler as programming a custom TYPO3 extension with a complex backend module.
Update 09/2022:
It is essential to update the TYPO3 Reference Index after using this method (direct db-access with SQL-UPDATE statements).
typo3cms referenceindex:update
Otherwise the "Ref" column in the "List" module view would still show a "-" (meaning 0) users belong in this feuser-group. After updating the refindex the "[Ref]" column will then display the approximate count of feusers.

Show attributes depending on user Jasperserver 8.0.0

I have made the following query:
SELECT pa.attrvalue, pa.attrname
FROM jiprofileattribute pa, jiuser u
WHERE pa.principalobjectclass = 'com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoUser' AND pa.principalobjectid = u.id AND
ORDER BY pa.attrname
The problem is that it returns all the attributes of all the users, and I need them to be from the respective user, I am using the community jasperserver so using tenantid is not an option for me, is there any trick to achieve this?

uSync Dropdown DataType Issue

I have 2 sites, dev branch and production. On my dev branch I'm using a couple of archetype DataType which are able to be configured by a simple dropdown with couple color names (like Green, Blue etc). I have like 300 published nodes which uses that datatype (required field). After I've exported "Full Export" in uSync dashboard and then copy/pasted the whole uSync folder to my production branch and clicked "Full Import". After import complete I check my nodes. All fields are there except that dropdown.
There are some old issues on the our.umbraco.com website stating the same issue, but they seem to been fixed.
I've posted there this issue, but has been 6 days, and the topic still is on manual approval.
Any idea what must be causing this issue?
I am using (uSync.BackOffice 4.0.16.0) (uSync.Core 6.0.15.0) [uSync.Content: 4.1.9.1]
Umbraco version 7.15.4
Thank you in advance.
Best regards,
Artur
PS. I am unable to create the USync label. Would appreciate if someone would edit with it!
I'd open up the database and look at the values in the cmsDataTypePreValues table. I suspect that uSync has changed the prevalues out from under you. Prevalues are really tricky and uSync does its best given the circumstances. You'll notice that the uSync .def files in Umbraco 7 don't record any unique ids on those prevalues. They just get inserted into the database and are assigned an id automatically. This means if the prevalues are deleted and recreated, they will have different ids. If those dropdown prevalues are being picked by the id field on the cmsDataTypePreValues record, that is probably what is going wrong.
Use the following query to see your prevalues for the datatype:
DECLARE #dataTypeNodeId AS INT = <dataTypeNodeId, INT, 0>
SELECT *
FROM cmsDataType dt
INNER JOIN cmsDataTypePreValues pv
ON pv.datatypeNodeId = dt.nodeId
WHERE dt.nodeId = #dataTypeNodeId
Compare the values you see here between the dev database and the production database. To help give you a better picture of what the data looks like, you could also run this query to see what the actual picked values look like. The query is so long because it is filtering out results from old versions. This might not work very well for you because your datatype is inside of Archetype. Hopefully it can still give you an idea about what selected dropdown values actually look like in the database.
DECLARE #dataTypeNodeId AS INT = <dataTypeNodeId, INT, 0>
SELECT TOP 1000 n.id
,n.[text]
,n.[path]
,pt.[alias] AS 'property alias'
,dtn.id AS 'Datatype Id'
,dtn.[text] AS 'Datatype Name'
,dtn.uniqueID AS 'Datatype Guid'
,d.templateId
,t.[alias] AS 'template alias'
,pd.dataInt
,pd.dataDate
,pd.DataNvarchar
,pd.dataNtext
,cv.VersionDate
FROM umbracoNode n
INNER JOIN cmsDocument d
ON d.nodeId = n.id
INNER JOIN cmsContentVersion cv
ON cv.VersionId = d.versionId
INNER JOIN cmsPropertyData pd
ON pd.contentNodeId = n.id AND pd.versionId = d.versionId
INNER JOIN cmsPropertyType pt
ON pt.id = pd.propertytypeid
INNER JOIN cmsDataType dt
ON dt.nodeId = pt.dataTypeId
INNER JOIN umbracoNode dtn
ON dtn.id = dt.nodeId
LEFT OUTER JOIN cmsTemplate t
ON t.nodeId = d.templateId
WHERE d.newest = 1
AND dtn.id = #dataTypeNodeId
You can try to manually fix the prevalue entries in the database. I've run into enough prevalue trouble with Umbraco dropdowns that I try to always use something like nuPickers to avoid picking prevalues by id.

Do ampersands work for user input in reports?

I have a working query that goes something like this:
Base table ACCT, link to others (listagg/subqueries) and ensure matching year("rollyear") field. Then the final step is to say which year ACCT table is in.
SELECT
FROM table ACCT
FULL OUTER JOIN table TABLE2 on ACCT.id = TABLE2.id and ACCT.rollyear= TABLE2.rollyear
...
FULL JOIN table TABLE7 on ACCT.id = TABLE7.id and ACCT.rollyear= TABLE7.rollyear
where ACCT.rollyear = extract (year from sysdate) +1
I typically use the calendar year plus one. I've been playing with using ACCT.rollyear = &rollyear to get user input... The limitation/issue I have is getting that running using the "User Defined Reports" feature.
Am I using this feature correctly? Does that only work for SQL Queries and not reports? Ive seen videos/comments about Stored Procedures and using "Accept...." but my attempts to mimic give errors and I'm not sure I'm on the right track. Thanks for any advice.
Change your query to use a bind variable:
where ACCT.rollyear = :rollyear
Then in the 'Binds' section you will see a variable with that name:
When you run your query you'll then be prompted to supply the value:

JDBCrealm FORM based problem. But BASIC working perfectly alright!

I successfully configured Glassfish to work with JDBCrealm using Basic Auth. But it's not working for Jsp page. My jsp page is simple using j_security_check and j_username and j_password. It throws me to UnAuthorizedAccess page (login error page). It's strange that it's working for basic auth and not for form based. What can be potential problem can anybody tell?
Also the structure of JDBCrealm table requirement is so ugly, i mean why is it so unnormalized? what if i want to change the structure? like
Users(Userid int, Username varchar(50), Userpassword varchar(50))
Roles(Roleid int, Rolename varchar(20))
UsersXRoles(UsersXRolesId int, UserId int, RoleId int)
??How should i configure this now?
Thanks in advance :)
I found a library that can do it: http://flexiblejdbcrealm.wamblee.org/
You can create a normalized database and create a view for Glassfish. We have the same layout that you described in your post and our view looks like this:
CREATE OR REPLACE VIEW v_user_role_relation AS
SELECT u.username, u.password, g.groupname
FROM user_group_rel ugr
JOIN users u ON u.user_id = ugr.user_id
JOIN groups g ON g.group_id = ugr.group_id::numeric;
However your other problem may have many reasons. Check if you defined your Realm in the server config and not only in the default config (that happened to me once).