Release 10.1A: OpenEdge Development:
Progress 4GL Reference

> ## CAN-DO function

> Checks a string value against two types of comma-separated lists:

> - An ID list of one or more user permission strings that indicate what users have access to the current procedure. The function returns TRUE if the specified user ID has access according to the list. Thus, you can implement run-time authorization for any procedure in your application.

> - An arbitrary list of string values. The function returns TRUE if the specified string value is contained in the list.

> #### Syntax

>     CAN-DO ( id-list [ , string ] )

> ``idlist``

> A constant, field name, variable name, or expression that evaluates to a list of one or more user IDs. If the expression contains multiple user IDs, you must separate the user IDs with commas. Do not insert blanks between the user IDs

> Table 10 lists values you can use in `idlist`.

> Table 10: Values to use for ID lists
> Value | Meaning
> --- | ---
> * | All users have access.
> `user` | This user has access.
> !`user` | This user does not have access.
> `string`* | Users whose IDs begin with `string` have access.
> !`string`* | Users whose IDs begin with `string` do not have access.

> You can use any combination of values to define `idlist`, and you must separate the values with commas.

> ``string``

> A character expression. The `string` is checked against`idlist`. If you do not enter `string,` the compiler inserts the USERID function that is evaluated each time you run the procedure. If the compiler inserts the USERID function, it does not reference a database name. If you use the USERID function and have more than one database connected, be sure to include the database name, for example, USERID “demo”.

> Examples

> The `r-cando.p` procedure is based on an activity permission table called `permission`. The permission table is not included in your demo database. However, the records in that table might look something like the following:

> Activity | Can-Run
> --- | ---
> custedit | manager,salesrep
> ordedit | manager,salesrep
> itemedit | manager,inventory
> reports | manager,inventory,salesrep

> In `r-cando.p` the FIND statement reads the record for the activity custedit in the permission table. (This assumes that a unique primary index is defined on the activity field.) The CAN-DO function compares the user ID of the user running the procedure with the list of users in the can-run field of the custedit record. If the user ID is manager or salesrep, the procedure continues executing. Otherwise, the procedure displays a message and control returns to the calling procedure.

> r-cando.p
>     DO FOR permission:
>       FIND permission "custedit".
>       IF NOT CAN-DO(permission.can-run)
>       THEN DO:
>         MESSAGE "You are not authorized to run this procedure".
>         RETURN.
>       END.
>     END.

> In this next example, the CAN-DO function compares `userid` (the user ID for the current user) against the values in `idlist`. The values in`idlist` include manager and any user IDs beginning with acctg except acctg8. If there is no match between the two values, the procedure displays a message and then exits.

> r-cando2.p
>     IF NOT CAN-DO("manager,!acctg8,acctg*")
>     THEN DO:
>       MESSAGE "You are not authorized to run this procedure.".
>     RETURN.
>     END.

> In addition to performing security checks, you can use the CAN-DO function for looking up any value in a comma-separated list. For example, the following procedure searches your `PROPATH` for your DLC directory:

> r-cando3.p
>     MESSAGE "The DLC directory " +
>             (IF CAN-DO(PROPATH, OS-GETENV("DLC")) THEN "is" ELSE "is NOT") +
>             " in your PROPATH.".

> #### Notes

> - If `idlist` contains contradictory values, the first occurrence of a value in the list applies. For example, CAN-DO(“abc,!abc*”,“abc”) is TRUE, since the user ID abc appears before!abc in `idlist`.

> - If `idlist` is exhausted without a match, CAN-DO returns a value of FALSE. Therefore, !abc restricts abc and everyone else (including the blank userid, ""). To restrict abc only and allow everyone else, use !abc,*.

> - A `userid` comparison against `idlist` is not case sensitive.

> - If a user is logged into the system as root, Progress allows access to the procedure even if access is denied by the `idlist.` You must specifically deny root access by adding `!root` to the `idlist`.

> - In addition to the examples shown above, you can use the CAN-DO function to compare a `userid` other than that of the current user against the list of values in `idlist`. For example, to assign a department `userid` to users “smith” and “jones” when they start Progress, you can prompt these users for a department`userid` and password. Progress then compares the supplied information against a table of identifiers.

> If the values supplied by the user match those in the identifier table, you can define a global shared variable for Progress to use for the entire session. The value of this variable is the department `userid`. Progress uses the CAN-DO function to compare `userid` (the value of the global shared variable) against the list of values in `idlist`.

> If you know the name of the global shared variable, you can define another variable with the same name and call subroutines directly.

> - You establish user IDs with the USERID and SETUSERID functions, or with the Userid (`-U`) parameter and Password (`-P`) parameter. The user ID can be an operating system user ID (on UNIX) or a user ID stored in the Progress _User table (in Windows or on UNIX).

> - Progress returns a Compiler error if you omit `userid` and one of the following conditions exists:

> - There is no database connected.
> - More than one database is currently connected.
> - CAN-DO outside of a VALIDATE statement is the same as FIND ... NO-ERROR followed by IF AVAILABLE(...).

> #### See also

> SETUSERID function, USERID function, VALIDATE statement

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095