Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Well I dont even know where to start with this one.

Status
Not open for further replies.

RGoldthorpe

Technical User
Aug 10, 2001
83
0
0
GB
Hello

I am hoping some of you out there may be able to give me an idea on how to do the following as my head is aching from all the banging on brick walls it has been doing.

Anyway let me explain from the beginning.

Basically my managers are suffering from an extreme case of paranoia. This I can do nothing about apart from try and pander to their whims :).

I have created a menu system that means that when a user logs in it enables and disables menu items depending on who has logged in. This works fabulously (even if I do say so my self.

Then they wanted on top of that to restrict access to organisational details depending on who they are.

not a problem can do that too.

Now what they want and what I am totally stuck on but I am hoping that one of you out there tells me I am stupid and it easy and to do it like this is.

Depending who the user logs on as and which organisation they want to view enables, disables, makes read only different parts of the form.

I.E organisations form has a pageframe with 3 tabs

Joe Bloggs logs on and has access to org test1 he can change the general tab, can read only the finance tab and the trading tab is disabled. But when he accesses organisation test2 he can view and change all tabs.

But when Jane Carter logs on and looks at test1 she has access to the trading tab and read only on the other two.

Sorry if I have repeated myself anywhere in this thread but I am truely stuck.

All help is more than appreciated

Rachel
 

Which part do you have trouble with? You seem to be able to detect "who is logged in" and you seem to be able to disbable menus items depending on who is logged in, so how is that process different with a pageframe? Although Pageframes do not a read-only property, the fields on the page do. Just use something like (In the activate event of each pages)
Code:
If Between(oApp.userlevel,1,3)
   thisform.pageframe1.page2.setall('Readonly',.t.,'Textbox')
Else
   thisform.pageframe1.page2.setall('Readonly',.f.,'Textbox')
endif

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Rachel,

my head is aching from all the banging on brick walls it has been doing.

The obvious solution is not to work in an office with brick walls. You can buy low-cost soft cladding from most DIY stores. This is the solution I have adopted when faced with similar problems.

Depending who the user logs on as and which organisation they want to view enables, disables, makes read only different parts of the form.

If the problem is confined to page frames, why not put code in the individual pages' Activate event? That code would drill down into all the containers and controls on the page, setting their read-only property as appropriate.

As for disabling the page frames, why not just do that in the form's Init? Or, are you saying that the user can navigate from one organisation to another within a form? If so, you need to disable / enable the pages every time you navigate. How you do that depends on how the code in the form is organised, but the concept should be clear enough.

On a more general level, Tek Tips member Marcia Akins has recently co-written a short series of articles on how to implement this sort of user-level security. It has appeared in the September to November 2004 issues of Foxtalk ( I recommend you to read it if you can get hold of it.

Mike


Mike Lewis
Edinburgh, Scotland

My Visual Foxpro web site: My Crystal Reports web site:
 
Thanks Mikes :)

I am off tho the DIY shop now to construct my self a sort of padded cubical arrangement and maybe a large mallet.

I have some falktalk magazines and my boss has the ones you mention and I have just knicked them :)I shall study them carefully. and see how best to put what I learn to good use.

thanks again

RAchel
 
Thanks Craig but this I have already done this bit I used this documnet to guide me too. It is the form access I am actually after doing now and individual fields on the form I need to do now

Thanks anyway

Rachel
 
Hi

The following is provided as example.

Code:
PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN

**************************************************
*-- Form:         form1 (e:\winners8\gl8\form1.scx)
*-- ParentClass:  form
*-- BaseClass:    form
*-- Time Stamp:   12/03/04 08:25:12 PM
*
DEFINE CLASS form1 AS form

    DoCreate = .T.
    Caption = "Form1"
    Name = "Form1"

    ADD OBJECT pageframe1 AS pageframe WITH ;
        ErasePage = .T., ;
        PageCount = 5, ;
        Top = 36, ;
        Left = 24, ;
        Width = 324, ;
        Height = 169, ;
        Name = "Pageframe1", ;
        Page1.Caption = "Page1", ;
        Page1.Name = "Page1", ;
        Page2.Caption = "Page2", ;
        Page2.Name = "Page2", ;
        Page3.Caption = "Page3", ;
        Page3.Name = "Page3", ;
        Page4.Caption = "Page4", ;
        Page4.Name = "Page4", ;
        Page5.Caption = "Page5", ;
        Page5.Name = "Page5"

    ADD OBJECT cmdexit AS commandbutton WITH ;
        Top = 216, ;
        Left = 24, ;
        Height = 27, ;
        Width = 84, ;
        Caption = "Exit", ;
        Name = "cmdExit"

    ADD OBJECT cmdsecurity AS commandbutton WITH ;
        Top = 216, ;
        Left = 120, ;
        Height = 27, ;
        Width = 96, ;
        Caption = "Build Security", ;
        Name = "cmdSecurity"

    ADD OBJECT cmdsetform AS commandbutton WITH ;
        Top = 216, ;
        Left = 228, ;
        Height = 27, ;
        Width = 120, ;
        Caption = "See How it Works", ;
        Name = "cmdSetForm"

    PROCEDURE init
       WITH ThisForm.PageFrame1
           FOR i = 1 TO .PageCount
              .Pages(i).AddObject('Text1','Textbox')
              .Pages(i).AddObject('Text2','Textbox')
              .Pages(i).Text1.Top = 24
              .Pages(i).Text2.Top = 48
              .Pages(i).Text1.Left = 12
              .Pages(i).Text2.Left = 12
              .Pages(i).Text1.Visible = .t.
              .Pages(i).Text2.Visible = .t.
           ENDFOR
       ENDWITH
    ENDPROC

    PROCEDURE buildpasstable
        LPARAMETERS lcName, lcCaption

        LOCAL lo, lcCaption1, i
        lo = EVALUATE(lcName)

        DO CASE
           * If lo is PageFrame
           CASE UPPER(lo.BaseClass) = [PAGEFRAME]
              FOR i = 1 TO lo.PageCount
                 * Insert the Page in PassTable
                 IF EMPTY(lcCaption)
                    lcCaption1 = lo.Pages(i).Caption
                 ELSE
                    lcCaption1 = lcCaption + [-] + lo.Pages(i).Caption
                 ENDIF

                 LOCATE FOR ALLTRIM(lcName+[.]+ALLTRIM(lo.Pages(i).Name)) ;
                        == ALLTRIM(cCmd) AND ;
                     ALLTRIM(cUser) == ALLTRIM(pcUser) AND ;
                     ALLTRIM(cOrg) = ALLTRIM(pcOrg)
                 IF FOUND()
                    REPLACE cUser WITH pcUser, cOrg WITH pcOrg, ;
                       cName WITH lcCaption1, ;
                       cCmd WITH lcName+[.]+ALLTRIM(lo.Pages(i).Name)
                 ELSE
                   INSERT INTO PassTable (cUser, cOrg, cCmd, cName, lEnabled) ;
                      VALUES (pcUser, pcOrg, ;
                      lcName+[.]+ALLTRIM(lo.Pages(i).Name), ;
                      lcCaption1, .t.)
                 ENDIF
                 =ThisForm.BuildPassTable(lcName+[.]+lo.Pages(i).Name,lcCaption1)
              ENDFOR

           * If lo is a Page
           CASE UPPER(lo.BaseClass) = [PAGE]
              FOR EACH oControl IN lo.Controls
                  =ThisForm.BuildPassTable( lcName+[.]+oControl.Name, lcCaption)
              ENDFOR

           * If lo is a Button
           CASE UPPER(lo.BaseClass) $ [COMMANDBUTTON#TEXTBOX#GRID]
              * SUITABLY TAKE CARE TO INCLUDE VARIOUS BASE CLASS 
              * Insert the OBJECT in PassTable cursor

              LOCATE FOR ALLTRIM(lcName) == ALLTRIM(cCmd) AND ;
                 ALLTRIM(cUser) == ALLTRIM(pcUser) AND ;
                 ALLTRIM(cOrg) = ALLTRIM(pcOrg)
              IF FOUND()
                 REPLACE cName WITH lcCaption+[-]+lo.Name, ;
                         cCmd WITH lcName
              ELSE
                 INSERT INTO PassTable (cUser, cOrg, cCmd, cName, lEnabled) ;
                    VALUES (pcUser, pcOrg, lcName, ;
                       lcCaption+[-]+lo.Name, .t.)
              ENDIF
        ENDCASE
    ENDPROC

    PROCEDURE cmdexit.Click
        ThisForm.Release()
    ENDPROC

    PROCEDURE cmdsecurity.Click
        PUBLIC pcUser, pcOrg

        pcUser = INPUTBOX("Key in User Name")
        IF EMPTY(pcUser)
           RETURN
        ENDIF

        pcOrg = INPUTBOX("Key in Organization Code")
        IF EMPTY(pcOrg)
           RETURN
        ENDIF

        ** You can shift these code to the init of form
        IF ! FILE('PassTable.dbf')
           SELECT 0
           CREATE TABLE PassTable ;
               (cUser C(35), cOrg C(2), cName C(128), cCmd C(250), lEnabled L)
        ELSE
           SELECT 0
           USE PassTable ALIAS PassTable
        ENDIF

        ThisForm.BuildPassTable('ThisForm.PageFrame1')

        BROWSE FIELDS lEnabled, cName ;
           FOR ALLTRIM(cUser) == ALLTRIM(pcUser) AND ;
           ALLTRIM(cOrg) == ALLTRIM(pcOrg) ;
           TITLE "Set .t. or .f. appropriately"

        USE IN PassTable

        RELEASE cUser, cOrg
    ENDPROC


    PROCEDURE cmdsetform.Click
        **************************************************
        ** Instead of input boxes, suitably pass parameters
        LOCAL lcUser, lcOrg

        lcUser = INPUTBOX("Key in User Name")
        IF EMPTY(lcUser)
           RETURN
        ENDIF

        lcOrg = INPUTBOX("Key in Organization Code")
        IF EMPTY(lcOrg)
           RETURN
        ENDIF

        **************************************************
        ** LPARAMETERS lcUser, lcOrg

        ** First Set everything to default .t.
        WITH ThisForm.PageFrame1
           FOR i = 1 TO .PageCount
              .Pages(i).Enabled = .t.
              .Pages(i).SetAll('Enabled',.t.,'Textbox')
           ENDFOR
        ENDWITH
                
        ** Now set as per userid
        SELECT 0
        USE passTable ALIAS passTable

        SCAN FOR ALLTRIM(cUser) == ALLTRIM(lcUser) AND ALLTRIM(cOrg) = ALLTRIM(lcOrg)
           lcCmd = cCmd+[.Enabled = ]+TRANSFORM(lEnabled)
           &lcCmd
        ENDSCAN
        USE
    ENDPROC


ENDDEFINE
*-- EndDefine: form1
**************************************************

You can add 'Visible' property also suitably. But make sure that you dont trigger errors by adding Visible property for a page.

I have done similar security controls. But this is not copied from my application code in any part. I created with similar concept to what I use. It is not possible for me to provide the codes I use for obvious reasons.

However, the table is exposed and some one can edit, if they are smart.

The way to control that is another story. You have to make that table a part of DBC and trigger a .f. for any direct update attempts. The trigger can be controlled as part of your project Main.Prg code and not even stored in your DBC.

You can have the button to update the security and control that visible property only if logged as super user. SO you can update the property comfortably while the application is running.

:)

____________________________________________
ramani - (Subramanian.G) :)
 
MikeLewis,

Good joke - made my day! [bigsmile]

RGoldthorpe,

If you've subclassed the base classes then you could add this kind of functionality into the subclasses you've created and it will save you some time.

In either event, you are going to need some type of scheme in order to handle this. The problem as I see it is to provide the ability to handle so many different things turned on or off in so many different ways. That, I would guess, is the crux of your anguish. Not knowing all the variables here, and speaking from only my own experience with such things...I have found that turning on or off bits for a single variable works best. Then you can use bittest() function in order to find out what is on and what is off and so forth. Say that bit one being set is fullaccess, bit two being set is readonly, and neither bit being set is disabled. Then you can make everything on your forms disabled and if bittest(lnSecurity,1) make everything enabled, if bittest(lnSecurity,2) make everything readonly. This is an overly simplified example obviously what you are doing will be much more complex, but not impossible and perhaps a bit less complex than otherwise (no pun intended).

There are certainly plenty of examples of looping through all the controls on a form in this forum. Use one of those routines to set all the controls to their correct state in the init and have a function that will do the same as the user navigates the different records and their rights change. You will have to figure out a way to send the user to a different page or form if they are on one they shouldn't have access to when they navigate...that will be a bit of a bear but again not impossible.

You may think of creating a global function in your procedure file or main.prg that will handle all this looping and setting the properties to form controls and such. This will allow for easy maintenance.

Another thing you may find useful in some way is utilizing the tag property of the controls. The reason is that all controls no matter what they are has a tag property. I have used it in the past to put some string in it that holds information for the control and what type of behavior it should have when the user sees it or gives it focus. I only mention this in passing as you may be able to see some use for it given your current situation and your thoughts on working it out.

Last, but not least, good luck and I hope you are able to meet the requirements at hand given this and the other suggestions that were given here. Here's to paranoia and the job security it invariable creates for us all!


boyd.gif

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top