Jump to content

Security - related fields blank with FM server.


RNB-IT

This topic is 3194 days old. Please don't post here. Open a new topic instead.

Recommended Posts

We have record based security enabled with the security tab. the global var are loaded with data after the login of the user.

The rule is for viewing the Company data: 

If ( $$Account.Access_ALL ; 1; not IsEmpty ( FilterValues ( $$Account.Access_ID ;  _id  ) ) ) 

the _id field is for the Company, the rule is in context of the @Company table.

for the address table we have the rule 

( If ( $$Account.Access_ALL ; 1; not IsEmpty ( FilterValues ( $$Account.Access_ID ;  _id_company  ) ) ) )

_id_company is on the Address table, the rule is in the context of @Address table

when we relate the Company to the Address table with the data is correct displayed  on two separated layouts (one Company with data LA_Company and one Address with data LA_Address), and than the security works as expected for both layouts.

but when we make one layout LB_Company with an portal to LB_Address-Company  than on the version which is hosted on the server the portal with Address data is blank, but that's not the case when runs in the standalone version?

any suggestions are appreciated.

Thanks.

Link to comment
Share on other sites

Is the portal to @Address, or to another table occurrence of @Address?

Please consider when you use global variables for security, they can be viewed and modified using the data viewer.

Link to comment
Share on other sites

RNB-IT may have accidentally reported Tom's post instead of replying to it. Here is the content of his reply:

It was another TO, LB_Address-Company.

I Know about the $$vars are visible in the data viewer and is an not so good idea for security, but a global field is also not working correctly in the FMS 14.  So i want drill down to the level it works, and than move (upgrade) to an more secure solution.

When we use a privilege table with global fields for acces and connect the privilege table with an cartesian link (x) on the layout table LA_Company than still the portal is not showing the information in FMS 14, but standalone FM14 no problem at all.

Link to comment
Share on other sites

What if you add a Refresh Window[flush cached...] ?

By the way, you don't need a join, cartesian or otherwise, to access global fields. You can read and write to them regardless of context.

Link to comment
Share on other sites

Here is a test file,  in the standalone version it works as expected, upload the version to an FMS14 and no data is shown in the portal.

to have full access use admin password admin

to have limited record acces use: name: hans password: hans

all suggestions are welcome 

TestApp.fmp12

Link to comment
Share on other sites

The file does not want to open... (The translator for this file....)

Could it be a timing issue / order of sequence issue?  If the relevant part of the RLA calc is not updated *before* the RLA calc fires then the RLA result may not give you want you need.

 

 

 

Link to comment
Share on other sites

Nope, even the zip file won't uncompress.  "Unarchiver" says the file is not complete.

I did some troubleshooting on this about 6 months ago.  One way to help you see what is happening is to do this:

1- change your RLA calc so that it starts with this:

Let(

$$log = List( $$log ; "priv set evaluated at " & get(CurrentTimeUTCMilliseconds) ) ;

<rest of your calc here>

)

2- on your layout put a field in the top left corner and use conditional format to give it this calc.  Make sure this object is completely sent to the back of the stacking order

Let(

$$log = List( $$log ; "first object drawn on layout " & get(CurrentTimeUTCMilliseconds) ) ;

1
)

3- on your layout put a field in the bottom right corner and use the same cond format calc but to say "last object".  Make sure this object is completely brought to the front of the stacking order

4- whatever script that sets your RLA calc relevant parts: make it log the same way too.

Now whenever you log in and go to that layout you will see a log of the exact sequence of events, when things are drawn and when things get evaluated.

Back when I looked at it, I noticed there is a very real difference in the sequence when you use a global field vs a variable.

Once you understand the sequence you'll see where you can tweak it.  Note that we don't have full control over that sequence, some of it is completely governed by FM.

 

 

 

 

  • Like 1
Link to comment
Share on other sites

Hi,

thanks for the explaintion of the log files, very nice, but still can not get the security rules working on the server version.

what i see is that in the log files of the server version the portal is only evaluated for record number 0, (new records), but not for the record that should be displayed.

STANDALONE

first object record# 1 at 63572836260608
priv PERSON set evaluated record# 1 at 63572836260608
priv ADDRESS set evaluated record# 8 at 63572836260609
priv ADDRESS set evaluated record# 1 at 63572836260609
last objectevaluated record# 1 at 63572836260610
first object record# 1 at 63572836260610
last objectevaluated record# 1 at 63572836260610
priv PERSON set evaluated record# 1 at 63572836260611
priv ADDRESS set evaluated record# 1 at 63572836260611
PORTAL Fieldevaluated record# 1 at 63572836260611
PORTAL Fieldevaluated record# 1 at 63572836260611
priv PERSON set evaluated record# 1 at 63572836260615
priv ADDRESS set evaluated record# 1 at 63572836260615
priv ADDRESS set evaluated record# 1 at 63572836260616
priv ADDRESS set evaluated record# 0 at 63572836260617
priv ADDRESS set evaluated record# 0 at 63572836260617
priv PERSON set evaluated record# 1 at 63572836260618

SERVER OUTPUT

first object record#: 1 at 63572836436271
priv PERSON set evaluated record#: 1 at 63572836436271
last object record#: 1 at 63572836436279
first object record#: 1 at 63572836436280
last object record#: 1 at 63572836436280
priv PERSON set evaluated record#: 1 at 63572836436280
Portal Field object record#: 1 at 63572836436281
priv PERSON set evaluated record#: 1 at 63572836436284
priv ADDRESS set evaluated record#: 0 at 63572836436285
priv ADDRESS set evaluated record#: 0 at 63572836436289
priv PERSON set evaluated record#: 1 at 63572836436291
priv PERSON set evaluated record#: 1 at 63572836438391
priv PERSON set evaluated record#: 1 at 63572836438391
priv PERSON set evaluated record#: 1 at 63572836438391
priv PERSON set evaluated record#: 1 at 63572836438392
priv PERSON set evaluated record#: 1 at 63572836438410
priv PERSON set evaluated record#: 1 at 63572836438410
priv PERSON set evaluated record#: 1 at 63572836438411
priv PERSON set evaluated record#: 1 at 63572836438411

 

 

Link to comment
Share on other sites

A couple of things.

A calculation like this is a monster; don't nest function calls if you want to be able to read it and understand it next week, or by anyone else that needs to look at it.

Let(

$$log = List( $$log ; "priv ADDRESS set evaluated record# " & Get (RecordNumber) & " at " & Get(CurrentTimeUTCMilliseconds) ) ;

( not IsEmpty ( FilterValues ( FilterValues ( Get ( AccountExtendedPrivileges ) ; SC_Users::privileges ) ; "Address1View" ) ) )
	and 
( If ( SC_Users::access_all ; 1 ; not IsEmpty ( FilterValues ( SC_Users::accesss_id ; _id_Person ) ) ) )
)

 

Break it down in manageable statements inside the Let() function.  I have no idea what I'm reading here.

The other thing to consider is to think hard about the "evaluate this calculation from the context off" in the top left corner of the priv set calculation (as with any other calculation)...

 

 

Link to comment
Share on other sites

At the very least, add a comment that expresses in normal english what should happen so that someone that reviews can check the purpose against the actual.

 

As was written in Structure and Interpretation of Computer Programs (aka SICP), the seminal textbook of programming taught for years at MIT, “A computer language is not just a way of getting a computer to perform operations … it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.” A great program is a letter from current you to future you or to the person who inherits your code. A generous humanistic document.

As a last thought for tonight, I'm note sure that Get(RecordNumber) in a priv set calc is the same as the Get(RecordNumber) that you think the user is looking at.  Use the primary key of the record for the logging function to be certain.

Edited by Wim Decorte
Link to comment
Share on other sites

The file is still unreadable.

This is just really basic stuff; it is hard to see why you're having a problem with this.

It is NOT in a Dropbox folder, right?

It is NOT being served by FileMaker Server, right?

If locally opened, you really did QUIT FileMaker right?

Link to comment
Share on other sites

Hi BruceR

NOT in a dropbox folder, NOT served By file maker, File maker Closed, and on all my other computers i can uncompress the without any problem. I think that the fmforums upload is the problem, there is something going wrong at that point, maybe file size?

If you like send me your email and i will we-transfer it.

 

Link to comment
Share on other sites

Hi Wim,

You're are right, nesting could be difficult to read, but there is only one nesting in both lines...

1 line:

Your line,  with one statement more, to see where the switch is in the $$log between two records, and i will set it to the primary key.

2 line:

Has the user (group) the rights that are defined in the extended privilege set, 

and is the result correct to see the information as defined.

3 line

has the user rights to see all information , or is it limited to just a few records.

In an let statement it would not be much better:

let (  [

// get the user rights to access the table
~privilegeUser =FilterValues ( Get ( AccountExtendedPrivileges ) ;  SC_Users::privileges ) ;
~privilegeDef = FilterValues ( ~privilegeUser ; "Address1View" ) ;
~privilegeAccess = not isEmpty ( ~privilegeDef  ) ;

// get the user rights to access the records by id 
~idUser = FilterValues (  SC_Users::accesss_id ; _id_Person ) ; 
~idUserAllowed = not isEmpty ( ~idUser ) ;
~idAcces = If ( SC_User::access_all and ~idUserAccess ; 1 ; 0 ) ; 
// result
$result = If ( ~privilegeAccess and ~idAccess ; 1 ; 0 ) ]

$result )

The last part for the _id's  is necessary for displaying related information on the same layout with the appropriate rights for the user.

On part of the " evaluate this calculation from the context off":  because the calculation is one that has to be universal for ALL layouts, i use a separated TO's structure, with connections based on the AccountName.
 

I,  see one typo error

~idAcces = If ( SC_User::access_all and ~idUserAccess ; 1 ; 0 ) ; 
should be
~idAcces = If ( SC_User::access_all or ~idUserAccess ; 1 ; 0 ) ; 
 
Link to comment
Share on other sites

Here's my version, wrote it on the plane-ride to Las Vegas

 

Let(
[
$$log = List( $$log ; "priv ADDRESS set evaluated record# " & Get (RecordNumber) & " at " & Get(CurrentTimeUTCMilliseconds) ) ;

_has_all_access = if( SC_Users::access_all = <what?> ; true ; false ) ;

_user_privs = FilterValues ( Get ( AccountExtendedPrivileges ) ; SC_Users::privileges ) ;
// why this?  why not just tke the Account ext privs?


_has_address_view = if( isempty( FilterValues ( _user_privs ; "Address1View" )) ; false ; true ) ;

_owns_record = if( IsEmpty ( FilterValues ( SC_Users::accesss_id ; _id_Person ) ) ; false ; true )

];

case(
_has_all_access = true ; true ;
_has_address_view = true and _owns_record = true ; true ;
false

)

)

 

Note that I'm a lot more explicit in the IF statements.  One reason for that for instance is where you do IF(

SC_Users::access_all

)

 

That field is a text field so it can contain pretty much anything.  If I read your calc I have no clue what you are testing in the IF.  I can ASSUME it will contain 1 or 0 but why not just be explicit so that there are no assumptions?

Link to comment
Share on other sites

Hi

_user_privs = FilterValues ( Get ( AccountExtendedPrivileges ) ; SC_Users::privileges ) ;
// why this?  why not just tke the Account ext privs?
when there is a version update of my application not all users have to (re)set a new password,  the administration of all users is from an table Users, i known security wise it is better to add the users in filemaker, but you can limit the access to this table in a way that the table is only available for Admin (full access) or a few moments at the log-in window, and otherwise it is only readonly. The password is stored as MD5 in the file and all other security fields should be memory based (globals), this configuration is not yet set in the testApp.
 
SC_Users::access_all
of course the value is only 1 or 0, may be it's better to use the custom function like  #boolean ( SC_Users::access_all ) than it's even more flexible, reusable than hard coding.

I like the discussion about the style of coding and readablity of the coding, that's is every important, but the record level privilege problem in Filemaker Server is still an issue... andi really want to solve it.

 

Link to comment
Share on other sites

 

SC_Users::access_all
of course the value is only 1 or 0
 
Nothing "of course" about it.  The field is empty in your test file and it is a text field so it could be a lot of things including multiple values.  Easy to make a mistake there and your code offers no comments or other explanation.
 

 

I like the discussion about the style of coding and readablity of the coding, that's is every important, but the record level privilege problem in Filemaker Server is still an issue... andi really want to solve it.

 

The two go hand-in-hand so don't dismiss it.  You're asking us to look at your and help figure out what the issue could be; we can't do that if the code is not transparent.

As Barbara already indicated and I have too; this kind of issue behaves differently when using variables vs. global fields and in both our cases it worked as expected when using global fields.  Given that, I'm still trying to determine if there is anything in your code that is not what you expect it to be.

 
 
 
Link to comment
Share on other sites

Hi I got the problem.... <missing index> warning for the records /fields in the table SC_Person and SC_Address.

The structure of the tables in the graph, in basic a "selector - connector" soultion:

SC_USERS  -- SC_Person  ( link on username   =   ACCOUNT.NAME )

ACCOUNT.NAME is a calculated field with the value $$Accountname, which is initialized at the log-in screen.

SC_USERS is connected to the layout table with x_Joins  according to the selector connector solution.

If we place one field  from the SC_Person on my layout it says <missing index>.

When we change the link to an x (cross)

SC_USERS  -- SC_Person  ( on username   x   ACCOUNT.NAME ) it works.

And the link is only used to see all files, so the ACCOUNT.NAMe can be removed and use the x_Join field.

thanks for all the assistance and ideas, for coding

Ruud

Link to comment
Share on other sites

This topic is 3194 days old. Please don't post here. Open a new topic instead.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.