Alpha Software Mobile Development Tools:   Alpha Anywhere    |   Alpha TransForm subscribe to our YouTube Channel  Follow Us on LinkedIn  Follow Us on Twitter  Follow Us on Facebook

Announcement

Collapse

The Alpha Software Forum Participation Guidelines

The Alpha Software Forum is a free forum created for Alpha Software Developer Community to ask for help, exchange ideas, and share solutions. Alpha Software strives to create an environment where all members of the community can feel safe to participate. In order to ensure the Alpha Software Forum is a place where all feel welcome, forum participants are expected to behave as follows:
  • Be professional in your conduct
  • Be kind to others
  • Be constructive when giving feedback
  • Be open to new ideas and suggestions
  • Stay on topic


Be sure all comments and threads you post are respectful. Posts that contain any of the following content will be considered a violation of your agreement as a member of the Alpha Software Forum Community and will be moderated:
  • Spam.
  • Vulgar language.
  • Quotes from private conversations without permission, including pricing and other sales related discussions.
  • Personal attacks, insults, or subtle put-downs.
  • Harassment, bullying, threatening, mocking, shaming, or deriding anyone.
  • Sexist, racist, homophobic, transphobic, ableist, or otherwise discriminatory jokes and language.
  • Sexually explicit or violent material, links, or language.
  • Pirated, hacked, or copyright-infringing material.
  • Encouraging of others to engage in the above behaviors.


If a thread or post is found to contain any of the content outlined above, a moderator may choose to take one of the following actions:
  • Remove the Post or Thread - the content is removed from the forum.
  • Place the User in Moderation - all posts and new threads must be approved by a moderator before they are posted.
  • Temporarily Ban the User - user is banned from forum for a period of time.
  • Permanently Ban the User - user is permanently banned from the forum.


Moderators may also rename posts and threads if they are too generic or do not property reflect the content.

Moderators may move threads if they have been posted in the incorrect forum.

Threads/Posts questioning specific moderator decisions or actions (such as "why was a user banned?") are not allowed and will be removed.

The owners of Alpha Software Corporation (Forum Owner) reserve the right to remove, edit, move, or close any thread for any reason; or ban any forum member without notice, reason, or explanation.

Community members are encouraged to click the "Report Post" icon in the lower left of a given post if they feel the post is in violation of the rules. This will alert the Moderators to take a look.

Alpha Software Corporation may amend the guidelines from time to time and may also vary the procedures it sets out where appropriate in a particular case. Your agreement to comply with the guidelines will be deemed agreement to any changes to it.



Bonus TIPS for Successful Posting

Try a Search First
It is highly recommended that a Search be done on your topic before posting, as many questions have been answered in prior posts. As with any search engine, the shorter the search term, the more "hits" will be returned, but the more specific the search term is, the greater the relevance of those "hits". Searching for "table" might well return every message on the board while "tablesum" would greatly restrict the number of messages returned.

When you do post
First, make sure you are posting your question in the correct forum. For example, if you post an issue regarding Desktop applications on the Mobile & Browser Applications board , not only will your question not be seen by the appropriate audience, it may also be removed or relocated.

The more detail you provide about your problem or question, the more likely someone is to understand your request and be able to help. A sample database with a minimum of records (and its support files, zipped together) will make it much easier to diagnose issues with your application. Screen shots of error messages are especially helpful.

When explaining how to reproduce your problem, please be as detailed as possible. Describe every step, click-by-click and keypress-by-keypress. Otherwise when others try to duplicate your problem, they may do something slightly different and end up with different results.

A note about attachments
You may only attach one file to each message. Attachment file size is limited to 2MB. If you need to include several files, you may do so by zipping them into a single archive.

If you forgot to attach your files to your post, please do NOT create a new thread. Instead, reply to your original message and attach the file there.

When attaching screen shots, it is best to attach an image file (.BMP, .JPG, .GIF, .PNG, etc.) or a zip file of several images, as opposed to a Word document containing the screen shots. Because Word documents are prone to viruses, many message board users will not open your Word file, therefore limiting their ability to help you.

Similarly, if you are uploading a zipped archive, you should simply create a .ZIP file and not a self-extracting .EXE as many users will not run your EXE file.
See more
See less

Web Security Functions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #16
    Re: Web Security Functions

    Couple educational points before the example. Ignore it if you want to stay less confused!

    If you have both an Email and a Userid control on your dialog, it means to me that your Userid is a non-email address value, like "stevewood". But if (only if) your Userid is supposed to be an email address, and it is supposed to be the same value as the field you have named Email, then remove the Email field entirely. Since Security will still want an email address (redundant to the Userid) include this statement anywhere above the a5ws_save_user_values() statement: request.variables.email = currentform.controls.userid. That will effectively copy your Userid in to the Email field, and make them consistent.

    The only possible acception to the above is if you want the Userid to be one email address, and the Email (for use in password recovery) to be a different email address.

    Your statement request.variables.email = "" means you want the email address to be blank when saved to Security, probably not what you want. Plus it will cause your dialog to report an error "Email: Required Data Missing" since it wipes out the email value, which Security expects.

    Your statement request.variables.guid = "" is redundant IF you have a field named guid in the dialog. The fact that the field exists replaces the need for a specific request variable with that name. In your dialog, the guid will be hidden and blank. Because it is blank, Security will attempt to add the record as a new user. If it is not blank, it will attempt to locate a user with that guid and update their record and, if it cannot find a record with that guid, it will attempt to add them.

    EVENTS

    INITIALLIZE
    a5ws_get_user_values(CurrentForm,request)
    ' this is only necessary if you are trying to CHANGE an existing users Security record. The function takes guid, ulink or userid (you should only specify one) and if it finds a matching record in Security, it brings over the values to the dialog. An example might be:

    request.variables.userid = "[email protected]"
    a5ws_get_user_values(CurrentForm,request)

    This will cause that userid to be looked up in Security, and fill the dialog with values. The explicit value could be replaced with a session variable or a page variable. The Alpha Help document includes an example where a page variable is used.

    VALIDATE
    a5ws_save_user_values(CurrentForm,request)
    'This will seem odd if you are used to writing code for the validate event. The function does two things: 1) it saves the values from the dialog to Security, 2) it runs validation based on the Security model (not your dialog's validation). For example, if you omitted the userid, this step would report back an error.

    AFTER VALIDATE
    a5ws_get_user_values(CurrentForm,request)
    'That would be all you need if you were only saving values to Security. If you are also saving values to a local Users table (like Firstname, Lastname, etc.) you would need proper code to save those values. I will put a complete example of that at the bottom of this post. This event will have the most variation of code depending on what you are doing.

    ACTIVATE
    grouplist = a5ws_get_groups(request,.T.)
    secques = a5ws_get_security_ques(request)

    'Those two functions return lists from Security that might be used in your dialog. If you show Group Permissions, base your Checkboxes on the variable named grouplist. If you include Security Questions, base the dropdowbox on the variable secques.

    ============================
    Annotated example of a more complete AFTER VALIDATE event

    Code:
    're-Get values from Security (which you just saved in the Validate event) 
    a5ws_get_user_values(CurrentForm,request)
    ' I like to write who was just added to a session variable for display on the A5W page
    session.message = "Just added " + currentform.controls.userid
    'open my Users table to save the extra information
    dim tbl as p
    tbl=table.open("[PathAlias.ADB_Path]\users")
    tbl.index_primary_put("id")
    recnum = tbl.fetch_find(alltrim(CurrentForm.Controls.userid))
    IF (recnum>0) THEN
    	'do nothing since security will not allow duplicates
    	' this dialog is for adding, not updating
    	else
    	tbl.enter_begin()
    	tbl.fname = currentform.controls.fname.value
    	tbl.lname = currentform.controls.lname.value
    	tbl.created = date()
    	tbl.enter_end()
    end if
    ' Get the new ID back as my Ulink. The Id in the table is an auto-increment field
    ' Because I place the ID into a request variable named ulink, it will save to Security
    request.variables.ulink = tbl.Id
    tbl.close()
    
    'I'd only include the line below if my Userid IS an email address and I want the Security Email field to be populated with the same email address. In this case, I would have no Email field in my dialog
    'request.variables.email = currentform.controls.userid
    
    ' I have to re-save to Security because I have a new Ulink value and potentially a new Email value.
    a5ws_save_user_values(CurrentForm,request)
    
    ' Optional, this code blanks out most of the dialog fields to they are ready for the next user to be added
    currentform.controls.guid = ""
    currentform.controls.fname = ""
    currentform.controls.lname = ""
    currentform.controls.password = ""
    currentform.controls.password_confirm = ""
    currentform.controls.secans = ""
    currentform.controls.userid = ""
    currentform.controls.ulink = ""
    currentform.controls.lname = ""
    currentform.controls.fname = ""
    Steve Wood
    See my profile on IADN

    Comment


      #17
      Re: Web Security Functions

      Steve,
      Above and beyond as usual! Thank you very much. Wish I knew enough to help you out once in a while. I'm learning!
      Eric

      Alpha Five Websites
      longlivepuppies.com
      socialservicenetwork.com
      -------------------------------------------------
      socialservicenetwork.org

      Comment


        #18
        Re: Web Security Functions

        <<Wish I knew enough to help you out once in a while>> Teaching me how to "retire at 48" (from your other post) might be a good start :). I think you gave the general instructions in that post. By the way, I always hold back on providing an attached dialog or a whole 'example' project, even though I have that, because I think people should go through the exercise of creating them on their own. And I know that is what you want. If someone wants it built it for them, that's why I am here as a consultant.
        Steve Wood
        See my profile on IADN

        Comment


          #19
          Re: Web Security Functions

          Once again, thank you Steve.
          <<I always hold back on providing an attached dialog or a whole 'example' project, even though I have that, because I think people should go through the exercise of creating them on their own. And I know that is what you want.>> I agree. Doing and problem solving on your own forces one to learn and use that knowledge on the next project segment. However, (speaking for myself now) there have been times when better direction (good and correct examples) have allowed me to move on and gain more confidence. Like others have stated in this forum, your help is invaluable and I appreciate it!

          This is what I've done with my Aftervalidate

          a5ws_get_user_values(CurrentForm,request)
          ' ============= Updates my users table ============
          tbl = table.open("[pathalias.adb_path]\users")
          query.filter = "userid =" + s_quote(CurrentForm.Controls.Userid.value)
          query.order = ""
          query.options = ""
          indx = tbl.query_create()
          update.fields = 4
          update.field1 = "Email"
          update.expr1 = s_quote(CurrentForm.Controls.Email.value)
          update.field2 = "Secquest"
          update.expr2 = s_quote(CurrentForm.Controls.SecQues.value)
          update.field3 = "Secanswer"
          update.expr3 = s_quote(CurrentForm.Controls.SecAns.value)
          update.field4 = "Password"
          update.expr4 = s_quote(CurrentForm.Controls.Password.value)
          tbl.update()
          tbl.close()

          ' ========== Once submit is clicked, User is redirected to proper home page
          If alltrim(lookupc("F",alltrim(session.__protected__userid),"alltrim(Permissions)","[pathalias.adb_path]\users","userid")) = "Employer"
          CurrentForm.RedirectTarget = "EmployerHomePage.a5w"
          else If alltrim(lookupc("F",alltrim(session.__protected__userid),"alltrim(Permissions)","[pathalias.adb_path]\users","userid")) = "JobSeeker"
          CurrentForm.RedirectTarget = "JSHomePage.a5w"
          end if

          ---> I'm allowing the user to change/update more than the email address
          ---> The only problem that remains for me is to correctly populate the dropdown list for the security question. Currently when I use dropdown, it defaults to the first question, NOT what the user initially chose when registering. This would cause a problem if the user is not alert to this.
          Last edited by EricN; 04-19-2008, 11:41 PM.
          Eric

          Alpha Five Websites
          longlivepuppies.com
          socialservicenetwork.com
          -------------------------------------------------
          socialservicenetwork.org

          Comment


            #20
            Re: Web Security Functions

            Eric,

            Couple things, even though they don't address your question:

            Do not use tbl.update() at all for this. It is intended for bulk updates. Use what I suggested or similar. To my code, where it opens the table, you would fill in the IF TRUE with a tbl.change_begin() sequence.

            Do not - do not - do not (everyone) include all those fields in your local Users table (password, secquestion, secanswer, permissions). They belong to Security only and your storage in the Users table is redundant and less safe. That would go also for Email and Userid, except they are often immediately useful and handy sitting in the Users table, but then you have to keep them in sync with Security if changed.

            If you need to redirect based on Sec Group, use one of the a5ws_ functions that determines the users group when logged in. You can even include when you add the user to Security by adding request.variables.RedirPage
            = "mypage.a5w" at the right place.

            For reference (not that I know everything), my default local Users table looks like this:

            Id Character 5 0
            Userid Character 60 0
            Fname Character 50 0
            Lname Character 50 0
            Emailok Logical 1 0
            Readterms Logical 1 0
            Lastlogin Time 17 0
            Regstatus Character 10 0
            Regdate Date 8 0
            Regsource Character 10 0
            Regtemp Character 80 0
            • The Userid is redundant to the Userid in the Security but convenient sitting in the Users table. The Userid is typically an Email address.
            • The ID is an autoincrement and matches the Ulink in Security.
            • EmailOK means they opted-in to receive email from me.
            • ReadTerms means they read the Terms of Service when registering.
            • RegStatus is PENDING when they register, and ACTIVE when they confirm their registration.
            • RegSource tells how they registered (by Phone, Online, by an Admin, etc.)
            • Regtemp holds an encrypted copy of their password just between the time they are PENDING and ACTIVE.
            Steve Wood
            See my profile on IADN

            Comment


              #21
              Re: Web Security Functions

              Steve,
              Thank you for the corrections!

              I think you have admonished me in the past for using the update function. I'm sure you are correct. "Update is a high-level utility," you once said.

              Regarding the fields to update. You are absolutely correct. I'm one of the few who (I believe) do not require a high level of security. My project is a hobby. I initially had those fields in my users table because I didn't see a way for my users to make modifications in the future. Anyway I had a whole system developed around this. Now that I have a working dialog able to correctly change security fields, I will be taking these fields out of my local table. Email will probably be the only security field I leave in.

              I don't see a problem with my redirection. The user is already logged in when making the changes, therefore his permission is readily available via something like session.permissions or a LOOKUP. But you are probably correct and I'm not yet seeing the true value of your reasoning here.
              Last edited by EricN; 04-20-2008, 11:13 AM.
              Eric

              Alpha Five Websites
              longlivepuppies.com
              socialservicenetwork.com
              -------------------------------------------------
              socialservicenetwork.org

              Comment


                #22
                Re: Web Security Functions

                First off, Steve, thanks for the tutorial. The information was very helpful. I went through you lines of code and searched the help menu to get a better understanding of what you did. I can without a shadow of a doubt say I would have never gotten where you did without you help!

                I was able to create web users using the help item �Adding users with a web component�. You explained it very well what happens behind the scenes. My goal was to be able to go from my �CreateWebUsers� page to my local �user_information� table to have the user and the appropriate fields: first name, last name, address, phone , zip, email� I also want to list what security group they are part of. I only want the user to choose one, so I changed from checkbox to dropdown on the CreateWebUser page. I tried to tailor your example to fit my tables. For some reason I cannot figure out, the user data does not get to the �user_information� table. I did check to see if security recognized the creation of the user, and it does.

                For trouble shooting purposes, I also removed all the code in the after validate except the a5ws_get_user_values(CurrentForm,request) and tried to just blank out the dialog page with your optional code. The form that displayed is the same as when the submit button was hit.

                Any suggestions would be much appreciated!

                Thanks,

                Bob

                Here is my after validate page:

                a5ws_get_user_values(CurrentForm,request)

                dim tbl as p
                tbl=table.open("[PathAlias.ADB_Path]\user_information")
                tbl.index_primary_put("User_Id")
                recnum = tbl.fetch_find(alltrim(CurrentForm.Controls.User_Id))
                IF (recnum>0) THEN
                'do nothing since security will not allow duplicates
                ' this dialog is for adding, not updating
                else
                tbl.enter_begin()
                tbl.Enter_Date = date()
                tbl.User_Type = currentform.controls.groups.value
                tbl.Email = currentform.controls.email.value
                tbl.enter_end()
                end if

                request.variables.ulink = tbl.User_Id
                tbl.close()

                a5ws_save_user_values(CurrentForm,request)
                CurrentForm.RedirectTarget = "usernew.a5w"

                Comment


                  #23
                  Re: Web Security Functions

                  I'm looking for a little direction if anyone can help.

                  After adjusting my user table, I was able to save the security information to my local user table as Steve suggested. I used a radio button on my CreateWebUser page for group permissions so only one choice could be selected. I filtered out the Administrator choice. When I save the group permission to the user table, it is saved as a collection of numbers and letters. This in now way resembles one of my choices.

                  Does anyone have a suggestion on how to save the group permission as a character field that can be equal to choices presented?

                  Thanks in advance,

                  Bob

                  Comment


                    #24
                    Re: Web Security Functions

                    This code will convert choices to text assuming your control name is groups. But WHY would you want to save security groups to the user table? There are good reasons to do so under some special circumstances, but not normally.

                    glist = groups.dump("r")
                    ugroup = crlf_to_comma(glist)
                    Steve Wood
                    See my profile on IADN

                    Comment


                      #25
                      Re: Web Security Functions

                      Steve,

                      Thanks for taking the time to answer! I am brand new to building any type of database and I know I may be doing some things that would not be standard practice. I'm reading the posts and pull what I can from the 8100+ page help guide. I saw what you did with your user table (thanks). It helped along with all your other posts.

                      I have two types of users: offices, and clients. I initally planned on having two user tables, one for the offices and one for their clients, but I was not sure if I would still be able to use ulink to filter with both. A friend, non-A5, recommended using one user table and sort it based on the types of users. Hence, I thought of using the group selection when creating a web user, and save the choices in the user table along with the email. My user table would store: id, f & l names, address, phones, create date, email, and choose which office a client is subordinate to. I'll probably add a read terms selection and last login when I can figure how to do that.

                      Do you think in this case it would be ok to use the groups selection? If you have any other suggestions, if am very willing to hear! I am struggling, but the learning curve is steep.

                      Thanks again for your help,

                      Bob

                      Comment


                        #26
                        Re: Web Security Functions

                        That's not a bad reason to have the Groups in both security and the local table. Your purposes for the values are different in each location - security is for protecting pages and data based on Group. But your local copy of the "group" is for breaking out emails to each group. Think of what is in Security as something used when a particular person is logged in, to affect that persons experience and access to information. Security is not as convenient to, for instance, determing who all is in the Office group so you can send bulk email to all of them.

                        It will be easier overall if you have one users table.
                        Steve Wood
                        See my profile on IADN

                        Comment


                          #27
                          Re: Web Security Functions

                          Steve,

                          Thanks. I'm slowly making headway.

                          Bob

                          Comment


                            #28
                            Re: Web Security Functions

                            Ok, uncle. I�ve been trying for a couple of days and have gotten nowhere. I was unable to get Steve�s suggestion to work. I have a control group named �groups� in my CreateWebUser dialog page that I�m trying to save to a local user table in addition to web security user table. �Groups� is a Local, Radio Button, Character field. The radio button choice is a dynamic variable named �grouplist�. In the activate event, �grouplist � gets is choices from security and filters out �administrator� with:
                            grouplist = a5ws_get_groups(request,.T.)
                            grouplist = filter_string(grouplist,"Administrator",crlf(),.T.)
                            Part of which I don�t understand, if my groups in security display as character fields and they are classified as character fields in my CreateWebUser dialog page, why do they save in my users table as numbers and letters? I tried the following different codes to save the group selection in my local user table that all resulted in errors. With the errors, a user is created in security, but nothing is entered in the local user table.

                            glist = groups.dump("r")
                            ugroup = crlf_to_comma(glist)
                            tbl.usertype = ugroup
                            error: groups.dump method not found

                            All the following resulted in the error: fieldtypes don�t match.
                            glist = (currentform.controls.groups.value).dump("r")
                            ugroup = crlf_to_comma(glist)
                            tbl.Usertype = ugroup
                            error: field types don�t match

                            glist = (currentform.controls.groups.value).dump("r")
                            dim ugroup as C
                            ugroup = crlf_to_comma(glist)
                            tbl.Usertype = ugroup

                            dim glist as C
                            dim ugroup as C
                            glist = (currentform.controls.groups.value).dump("r")
                            ugroup = crlf_to_comma(glist)
                            tbl.Usertype = ugroup

                            glist = crlf((currentform.controls.groups.value).dump())
                            tbl.UserType = glist

                            glist = (currentform.controls.groups.value).dump("r")
                            ugroup = crlf_to_comma(glist)
                            tbl.usertype = ugroup

                            tbl.usertype = crlf((currentform.controls.groups.value).dump())

                            glist = crlf_to_comma((currentform.controls.groups.value).dump())
                            tbl.UserType = glist

                            Steve, I am taking what you�ve offered for assistance, and referencing it in the user guide to learn whatever I can. With only two user groups after �Administrator� is filtered, do I need the crlf_to_comma(), and not just crlf(). Also, if there are only two choices, and choosing a group is required, does that negate the need for �R�, which is used to remove blank entries in character arrays?

                            Anyone have any suggestions?

                            Thanks,

                            Bob

                            Comment


                              #29
                              Re: Web Security Functions

                              The system internally uses a modified UUID value (sometimes referred to as GUID) to identify the group. That is the series of numbers and letters you see. This allows the group name to be changed without changing the identifier. The web security system uses the identifier, not the name. The name is only there for display purposes. It is suggested that you save the identifier, as the name may change.

                              The syntax
                              Code:
                              grouplist = a5ws_get_groups(request,.T.)
                              Will actually return a list like this on a web page or in a component
                              Code:
                              Accounting|13ab8057496b46c2b53f20696189bfc9
                              Administrators|0c5bf62bf6a043d6a43edfb00c257a70
                              Clerical|94376d46c9e84fd3b4a14662d3154fad
                              Customers|74054c45c3c14b03a1d371d9190543bf
                              Marketing|b0a4afa5c9934454859c00944dd32c3f
                              The server adds most of the internal variables at run time in the later builds of Alpha Five Version 8 and all Version 9, so this works just as well to get the group list.
                              Code:
                              grouplist = a5ws_get_groups()
                              This list structure is the syntax needed to populate a dropdown, radio buttons, or checkboxes. When you make a selection from checkboxes, the result comes back as a pointer array, which is the reason to use the "dump" method. A dropdown or radio returns a simple character value. Both methods will return just the modified UUID value in currentform.controls.groups.value, such as "94376d46c9e84fd3b4a14662d3154fad", not the name. You can use the typeof() function to determine if the returned value from "groups" is an array or simple text. An array returns "P", and a simple string returns "C". You only need the dump method for the array.

                              There is a function to get the guid from the name, but not one to get the name from the guid. The method mentioned to use filter_string can can also be used to find the current name of a group. If you have an identifier of "94376d46c9e84fd3b4a14662d3154fad" and the list is as shown above, this returns the current name.
                              Code:
                              Grouplist=  a5ws_get_groups(request,.T.)
                              name = filter_string(grouplist,"94376d46c9e84fd3b4a14662d3154fad")
                              ' at this point,  name will equal  "Clerical|94376d46c9e84fd3b4a14662d3154fad"
                              ' get first word from string
                              name = word(name,1,"|")
                              'now name = "Clerical"
                              Filter_string() and word() are very fast and the conversion appears almost instantaneous.

                              Comment


                                #30
                                Re: Web Security Functions

                                Jerry,

                                Thank you for the explanation. I'll see if I can put it together to save the names in my local user table and report back.

                                Much appreciated,

                                Bob

                                Comment

                                Working...
                                X