FoxInCloud
wUserLogoff not clearing User Access
Gravatar is a globally recognized avatar based on your email address. wUserLogoff not clearing User Access
  n/a
  All
  Apr 27, 2015 @ 10:34am
Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James

Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  FoxInCloud Support - Thierry N.
  James Patterson
  Apr 27, 2015 @ 10:06pm
Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James


-- thn (FoxInCloud)

Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  n/a
  Thierry Nivelet (FoxInCloud)
  Apr 28, 2015 @ 01:34am
Oh, sure. I am removing the FIC comments and white space.

LPARAMETERS nButton, nShift, nXcoord, nYcoord

IF (TYPE('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN .T.&& Process event on server (ELSE block code)
ELSE

DODEFAULT()

IF TYPE('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb
THISFORM.wUserLogOff() && Remove User and log the out
THISFORM.RELEASE()
ELSE
CLEAR EVENTS
THISFORM.RELEASE()
ENDIF

ENDIF

Very simple. I have been using this as the startup window on the LAN side, so I stuck the CLEAR EVENTS on the LAN side. I will check to insure wUserLogOff() is the branch that is executing. I was wondering about the browser cache, it is NOT my friend! Any ideas?

- James


Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James


Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  FoxInCloud Support - Thierry N.
  James Patterson
  Apr 28, 2015 @ 08:33am
do you have code in .wUserGet()?


Oh, sure. I am removing the FIC comments and white space.

LPARAMETERS nButton, nShift, nXcoord, nYcoord

IF (TYPE('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN .T.&& Process event on server (ELSE block code)
ELSE

DODEFAULT()

IF TYPE('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb
THISFORM.wUserLogOff() && Remove User and log the out
THISFORM.RELEASE()
ELSE
CLEAR EVENTS
THISFORM.RELEASE()
ENDIF

ENDIF

Very simple. I have been using this as the startup window on the LAN side, so I stuck the CLEAR EVENTS on the LAN side. I will check to insure wUserLogOff() is the branch that is executing. I was wondering about the browser cache, it is NOT my friend! Any ideas?

- James


Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James




-- thn (FoxInCloud)

Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  n/a
  Thierry Nivelet (FoxInCloud)
  Apr 28, 2015 @ 09:39am
Yes:
RETURN _Screen.UserName

Which is a _Screen property set in .wUserSet().

- James


do you have code in .wUserGet()?


Oh, sure. I am removing the FIC comments and white space.

LPARAMETERS nButton, nShift, nXcoord, nYcoord

IF (TYPE('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN .T.&& Process event on server (ELSE block code)
ELSE

DODEFAULT()

IF TYPE('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb
THISFORM.wUserLogOff() && Remove User and log the out
THISFORM.RELEASE()
ELSE
CLEAR EVENTS
THISFORM.RELEASE()
ENDIF

ENDIF

Very simple. I have been using this as the startup window on the LAN side, so I stuck the CLEAR EVENTS on the LAN side. I will check to insure wUserLogOff() is the branch that is executing. I was wondering about the browser cache, it is NOT my friend! Any ideas?

- James


Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James





Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  FoxInCloud Support - Thierry N.
  James Patterson
  Apr 28, 2015 @ 09:55am
try to override .wUserLogOff():
lpara tlTemp
_Screen.userName = .null.
return dodefault(m.tlTemp)


Yes:
RETURN _Screen.UserName

Which is a _Screen property set in .wUserSet().

- James


do you have code in .wUserGet()?


Oh, sure. I am removing the FIC comments and white space.

LPARAMETERS nButton, nShift, nXcoord, nYcoord

IF (TYPE('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN .T.&& Process event on server (ELSE block code)
ELSE

DODEFAULT()

IF TYPE('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb
THISFORM.wUserLogOff() && Remove User and log the out
THISFORM.RELEASE()
ELSE
CLEAR EVENTS
THISFORM.RELEASE()
ENDIF

ENDIF

Very simple. I have been using this as the startup window on the LAN side, so I stuck the CLEAR EVENTS on the LAN side. I will check to insure wUserLogOff() is the branch that is executing. I was wondering about the browser cache, it is NOT my friend! Any ideas?

- James


Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James





-- thn (FoxInCloud)

Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  n/a
  Thierry Nivelet (FoxInCloud)
  Apr 29, 2015 @ 03:36am
Got me thinking... We have chatted about Login and wUserSet() and I have gone from a point of no understanding to a point of misunderstanding! ;)

I was not allowing wUserGet() to ever return a .NULL.

For the benefit of anyone else as dull as I, here is a brief statement of solution:

When you are testing or using your FIC website and you interact in almost any fashion with the web browser, and maybe see the WAITPIC graphic spinning, an AJAX call has been returned to the Server informing it of what you did. The server dutifully recreates the previous session for you. This includes rebuilding all cursors, forms,...everything. Your interaction with the web browser may have just been to bring it into focus, no form interaction yet, but this all still occurs. It is amazing that it is actually as fast as it is! A bit more to keep track of compared to the POST days.

The use of _Screen has bothered me since _Screen properties are essentially Public. After your comments and tracing the code, you would be surprised how many times wUserSet is called with just a button press, I now feel more comfortable with this situation. NO MATTER WHAT the user interaction, when the AJAX call hits the Server and the prior session is reconstructed, wUserSet is called before any response code is run. It is here that wUserSet will overwrite the Public _Screen property(s) and this makes them available to any following code, including wUserGet. A Public storage location is necessary to be in scope in later code. After all the code is run, a response is returned to the browser and the Server awaits another "hit". It also appears that the Server maintains the current session, so another hit from the same web browser will not require a reconstructed session. A hit from another web browser will cause the current session to be stored and a different user session reconstructed.

I rewrote wUserSet to follow the above statement and it now performs as needed. Lessons learned:

1. wUserSet must be able to process User info and Set at least a User to a variable (_Screen, Session, ...) that can be used further down the calling chain.

2. User will change depending on calling web browser, so wUserSet must assure that correct User is stored for use.

3. wUserLogOff depends on the fact that it changes the User value to .NULL. to complete the logoff.

4. wUserSet must allow .NULL. values to be Set.

5. Nulls are used as FIC can store any TYPE() for a User and .NULL. is the only way to indicate an empty User.

6. Forms will not run if wlAnonymousAllowed = .F. AND .wUserGet() returns .NULL. This secures forms against direct URL access.

7. If wUserSet is called multiple times in the same session, you can test for this and skip the Authentication and Authorization process.

Thierry, please correct any misconceptions above. I will probably forget this info and need it in a few months, so here it is! Hope this helps someone in the future.

- James



try to override .wUserLogOff():
lpara tlTemp
_Screen.userName = .null.
return dodefault(m.tlTemp)


Yes:
RETURN _Screen.UserName

Which is a _Screen property set in .wUserSet().

- James


do you have code in .wUserGet()?


Oh, sure. I am removing the FIC comments and white space.

LPARAMETERS nButton, nShift, nXcoord, nYcoord

IF (TYPE('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN .T.&& Process event on server (ELSE block code)
ELSE

DODEFAULT()

IF TYPE('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb
THISFORM.wUserLogOff() && Remove User and log the out
THISFORM.RELEASE()
ELSE
CLEAR EVENTS
THISFORM.RELEASE()
ENDIF

ENDIF

Very simple. I have been using this as the startup window on the LAN side, so I stuck the CLEAR EVENTS on the LAN side. I will check to insure wUserLogOff() is the branch that is executing. I was wondering about the browser cache, it is NOT my friend! Any ideas?

- James


Hi James

Can't reproduce the issue on my side.

I understand you have masterForm.wlAnonymousAllowed = .F.
Could you post the full code of your masterForm.button.click()? That'll help I believe.

TIA


Finally I am testing on the production server and I tested the app with a URL cut and paste after logout and still had access.

The Index.xxx form is a login and after successful login calls THISFORM.wUserLogIn(THISFORM.Inetauth.cName), which seems successful as all forms down the chain are available, and they have wlAnonymousAllowed = .F.

Index then calls the wFormMaster form. In the Master form is a button to logout and in it's click I call THISFORM.wUserLogOff(), and then Thisform.Release(). They are inside an "IF Type('m.thisForm.wlWeb') == 'L' AND m.thisForm.wlWeb" as I need a Clear Events in the LAN version.

Back to Index, as desired. Pasting Master form URL will still go to Master form.

Do I need to pass wUserLogOff() some parameters? I clear all user and password text in Index prior to calling the Master form, do I need to clear something before wUserLogOff() ?

TIA - James






Gravatar is a globally recognized avatar based on your email address. Re: wUserLogoff not clearing User Access
  FoxInCloud Support - Thierry N.
  James Patterson
  Apr 29, 2015 @ 05:26am
Hi James,

Thanks for this great summary / synthesis!
Looks like you appreciate FoxInCloud more and more - very nice to read!

I can only add one detail:
The .null. you refer to is the default value for the xxxServer.wUserAnonymous.

wUserAnonymous = .null.
&& {en} User ID meaning 'anonymous user' for your application
&& {en} Generally, it's a value of users table primary key that does not exist in the table
&& {en} For example, if User table PK is an integer, it could probably be 0

We chose this value because, at least in VFP, candidate and primary keys don't accept .NULL. values:

Index does not accept NULL (Error 1886)
Your key index expression evaluated to NULL, which is an invalid value an index.
This can often happen with a primary or candidate keys

Got me thinking... We have chatted about Login and wUserSet() and I have gone from a point of no understanding to a point of misunderstanding! ;)

I was not allowing wUserGet() to ever return a .NULL.

For the benefit of anyone else as dull as I, here is a brief statement of solution:

When you are testing or using your FIC website and you interact in almost any fashion with the web browser, and maybe see the WAITPIC graphic spinning, an AJAX call has been returned to the Server informing it of what you did. The server dutifully recreates the previous session for you. This includes rebuilding all cursors, forms,...everything. Your interaction with the web browser may have just been to bring it into focus, no form interaction yet, but this all still occurs. It is amazing that it is actually as fast as it is! A bit more to keep track of compared to the POST days.

The use of _Screen has bothered me since _Screen properties are essentially Public. After your comments and tracing the code, you would be surprised how many times wUserSet is called with just a button press, I now feel more comfortable with this situation. NO MATTER WHAT the user interaction, when the AJAX call hits the Server and the prior session is reconstructed, wUserSet is called before any response code is run. It is here that wUserSet will overwrite the Public _Screen property(s) and this makes them available to any following code, including wUserGet. A Public storage location is necessary to be in scope in later code. After all the code is run, a response is returned to the browser and the Server awaits another "hit". It also appears that the Server maintains the current session, so another hit from the same web browser will not require a reconstructed session. A hit from another web browser will cause the current session to be stored and a different user session reconstructed.

I rewrote wUserSet to follow the above statement and it now performs as needed. Lessons learned:

1. wUserSet must be able to process User info and Set at least a User to a variable (_Screen, Session, ...) that can be used further down the calling chain.

2. User will change depending on calling web browser, so wUserSet must assure that correct User is stored for use.

3. wUserLogOff depends on the fact that it changes the User value to .NULL. to complete the logoff.

4. wUserSet must allow .NULL. values to be Set.

5. Nulls are used as FIC can store any TYPE() for a User and .NULL. is the only way to indicate an empty User.

6. Forms will not run if wlAnonymousAllowed = .F. AND .wUserGet() returns .NULL. This secures forms against direct URL access.

7. If wUserSet is called multiple times in the same session, you can test for this and skip the Authentication and Authorization process.

Thierry, please correct any misconceptions above. I will probably forget this info and need it in a few months, so here it is! Hope this helps someone in the future.

- James



try to override .wUserLogOff():
lpara tlTemp
_Screen.userName = .null.
return dodefault(m.tlTemp)

© 1996-2024