Inconsistency with 'Readable If' and 'Writable If'
I wrote a comprehensive user permissions application that validates user permissions based on:
Entity > Location > Permission
Using a Global Function, I wrote this:
#{ obtain list of user permissions for entity or building NEW }#;
function permCheckN(ct : text,rid : number,permissionCompare : text) do
#{
Global Variables
}#;
#{
Entity permission checking variables
}#;
let obtainUserEntityAccess := (select int_entity_access where 'System User' = thisUserID());
let allEntityAccessCheck := first(obtainUserEntityAccess.int_is_sys_record = true) and
first(contains(obtainUserEntityAccess.int_entity_name, "ALL"));
let thisEntitySearch := first(obtainUserEntityAccess[int_is_sys_record = true or Entity = number(rid)]);
let entityAccess := if thisEntitySearch != null then
true
else
false
end;
let listEntityPerms := thisEntitySearch.int_permissions_list;
#{
Building permission checking variables
}#;
let obtainUserBuildingAccess := (select int_building_access where 'System User' = thisUserID());
let thisBuildingSearch := first(obtainUserBuildingAccess[int_is_sys_record = true or Building = number(rid)]);
let buildingAccess := if thisBuildingSearch != null then
true
else
false
end;
let listBuildingPerms := thisBuildingSearch.int_permissions_list;
#{
Check the user's permission
}#;
if isAdminMode() then
true
else
switch upper(ct) do
case "E":
if entityAccess = true or rid = 0 then
if contains(listEntityPerms, upper(permissionCompare)) then
true
else
false
end
end
case "B":
if buildingAccess = true or rid = 0 then
if contains(listBuildingPerms, upper(permissionCompare)) then
true
else
false
end
end
default:
false
end
end
end;
Ultimately, the function will return a Boolean true or false if the user has the appropriate permissions.
I call function:
permCheckN("B", int_building, "Personnel (Read)")
let's assume the returned result is TRUE. If this function is within 'Readable If' for a field and the output is true, the field is visible.
However, if I place the exact formula within 'Writable If', regardless of the output, the field will still be read-only.
I've even tried putting this function within a formula, and then trying
'Formula Field' = true;
but that still does not work. I am quite bummed, because a lot of work gone into this permissions structure, but its practically unusable due to a programming bug (I assume) within Ninox.
Doe anyone have any suggestions?
14 replies
-
bump.. hoping for input from someone.
-
Have you email Ninox support?
I tried with a Yes/No field in another table and had no issues using just the name or = true or = 1.
-
Hi Fred,
I finally sent my inquiry to support. Feel free to test the bug I discovered yourself with the attached database.
I assume this needs a deeper investigation by the development team.
1. Create a new record under 'System User' and set 'Ninox User' as yourself from the dropdown.
2. Add a user permission to yourself.
2a. Check 'System-Wide Access' (true)
2b. Set 'Role' to 'Role 1 - System'
3. Navigate to Test_Error page
3a. Field 'global function that returns true or false' should say "Yes"
4. Try to fill out Readable If, Writable If, and Read and Writable If.You will find that the Writable If fields cannot be modified. If you enter admin mode, click on the fields and look at "Display field only, if" and "Writable if" for each of the fields, you will find the logic within them is identical.
Thus, there is some backend underlying bug with Writable If.
-
Hi This is the oddest thing. I have tried so many permutations of your function. I have scrunched it down from
function permCheck(group_id_val : number,record_location_id : number,permission_text : text) do #{ ---------------------------------------- }#; #{ variables set for permission checking }#; let def_loc_check := number(record_location_id); #{ find the referenced (permission_text) permission id }#; let permission_id := number(first((select Permission)[upper('Permission Name') = upper(permission_text)]).Id); let curent_user := user(); #{ locate the current user in system users table }#; let return_user_id := first((select 'System User')['Ninox User' = curent_user]).Id; #{ return all permissions User Permissions linked to user_id and group_id_val }#; let matched_user_permission_group := (select 'User Permission')['System User' = return_user_id and group_id = group_id_val]; #{ compare permissions }#; switch group_id_val do case 1: if cnt(matched_user_permission_group[contains(return_permission_ids, permission_id)]) > 0 then 1 else 0 end case 2: if cnt(matched_user_permission_group[contains(return_entity_ids, record_location_id) and contains(return_permission_ids, permission_id)]) > 0 then 1 else 0 end case 3: if cnt(matched_user_permission_group[contains(return_building_ids, record_location_id) and contains(return_permission_ids, permission_id)]) > 0 then 1 else 0 end default: 0 end end;
To
function permCheck(group_id_val : number,record_location_id : number,permission_text : text) do let permission_id := number(first(select Permission where upper('Permission Name') = upper(permission_text)).Id); let return_user_id := number(first(select 'System User' where 'Ninox User' = user()).Id); let matched_user_permission_group := (select 'User Permission' where 'System User' = return_user_id and group_id = group_id_val); switch group_id_val do case 1: cnt(matched_user_permission_group[contains(return_permission_ids, permission_id)]) case 2: cnt(matched_user_permission_group[contains(return_entity_ids, record_location_id) and contains(return_permission_ids, permission_id)]) case 3: cnt(matched_user_permission_group[contains(return_building_ids, record_location_id) and contains(return_permission_ids, permission_id)]) default: 0 end;
I have moved from true / false to 1 / 0 and there are only two versions that make it work. The first is to just return a 1, the other is
sign(cnt(matched_user_permission_group[contains(return_permission_ids, permission_id)]))
The inclusion of sign() does work, over first(), number() but you can't use it as sign() return 1 when the value is 0.
Regards John
-
Wow! I didn't expect so many people to troubleshoot this. I really appreciate it.
Still waiting to hear back from support.
-
To put it simply, the permCheck function uses select statements to verify permissions in the tables. However, the select function does not work in the Writable If trigger that calls the permCheck function.
Therefore, we need to find a solution that does not use select to access permissions.
-
I've looked into this a bit more and is correct. The Ninox table level and field level Writable if... sections do not like select commands being used to return a value. Worth writing to support regarding this.
Regards John
Content aside
- 8 hrs agoLast active
- 14Replies
- 94Views
-
4
Following