Sw4   >   Misc   >   Misc (All Contents)
The oConstants object class is used to store any constant values which you want available to all of the class instances in your application. The oConstants object is instantiated using the startup task variable cn.
Property methods can be used to get and set constant values.
; Set the app mode.
Do cn.$:AppMode.$assign('web')
; Get the app mode.
Do cn.$:AppMode() Returns AppMode
To add your own constant to oConstants do the following:
You have the option of setting any of the oConstants property values from the startupsettings.txt file.
constants {
appmode = 'web' ;
}
Always remember to include the ; delimiter after each property. The property names are case insensitive.
Cached lists contain additional information about your StudioWorks application.
Cached lists are stored in the oModuleData objects classes. StudioWorks automatically creates an oModuleData object in a library when needed. Each module stores its own portion of each of the cached lists in its own oModuleData object. The oModuleDataTool is used to access the module data.
Cached lists save a lot of startup time. For larger applications it would take a lot of time to build the cached lists and the string tables cached list on startup.
When you open your app, StudioWorks loads the cached lists using the oModuleDataTool object class. The portions of each cached list which are stored in all of the libraries are merged together into master cached lists that are used by the application. The master cached lists are accessed through the applicable tvars. (lsts, stb, rprts, icns, etc.)
The oModuleData object of the applicable library. This is done so that you won't (shouldn't) lose any cached list changes made if Omnis Studio should crash on you.
is where you can view and edit the cached lists. When you make changes to a cached list item in the the changes are immediately saved to theSome cached list changes cascade to other cached lists. e.g. If you change the name of a schema class column, it could affect numerous query classes, and it will affect the string tables. The
does its best to do the cascading updates for you, but you may find a situations where it doesn't correctly cascade the changes. Please report these situations with as much details as possible so that they can be corrected in the StudioWorks framework.If you add a SQL class (schema or query) in the Omnis Studio IDE the cached lists will not be aware of the new SQL class. In order to add the SQL class to the cached lists you will need to click on it in the oModuleData object. As you make changes to the SQL class' meta-data each of the changes is saved back to the oModuleData object.
window of the . When you click on the new SQL class, the StudioWorks framework realizes it doesn't have that SQL class in its cached list and immediately adds the SQL class and its columns to the cached lists with all of the default values and saves it to the the SQL class' source libraryIf you are not using the VCS you should set the $alloweditifnotcheckedout Omnis Studio preference to kTrue. This will save StudioWorks from having to first test cascading updates to make sure any affected classes are checked out before actually doing the cascading updates. It will cut the time for cascading updates in half.
In pre-2008-07-31versions you were editing code or meta-data and then building the cached lists from your code or meta-data. As of the 2008-07-31 release you are now directly editing the cached lists, negating the need to 'rebuild lists'. In some cases it might feel a bit sluggish editing module data in the
If you want to see what is really in the cached lists, select the , but you are saving loads of time by not having to constantly rebuild cached lists. tab in the . This shows you exactly what is currently in each cached list. You can shift+click on any of the tabs in the to open the tab's subwindow in a stand alone window. The cached list window contents are refreshed each time the window comes to the top.When you are learning StudioWorks the easiest way to create a new StudioWorks app is by following the instructions given in the
. The takes you through the steps of modifying StartNewApp which is the demo app that comes which each release of StudioWorks.If you want to create a new app from scratch, here are the steps to follow:
Be sure to complete the
before you attempt to create a new app from scratch.
The section explains how to implement an observer using the oObserver class.
Observers are great for loose coupling of different subwindow instances. Suppose you are viewing a record in one subwindow and if the user changes to a different record you want another subwindow to be notifed when ever this happens. Observers are your friend for setting this up.The oObserver object class in swBase4 makes it very easy for you to set up and observer. There is also an oEventsObserver class which is a subclass of oObserver that specialized in notifying observers of event handling event.
To setup an observer you need to have an instance of oObserver inside the class where the change that you want to track will occur.
In order to attach an observer, we need to add an accessor method to the window class methods. Observers will use this method to subscribe for notifications when the thing they want to know about happens.
; Forward the message to the observer class instance.
Do ioChangeRecordObserver.$attach(pfrObserver,pCallBackMethod) Returns FlagOK
Quit method FlagOK
; Subscribe the list subwin to be notified when ever the edit window changes its record.
Do rEditSubWin.$attachChangeRecordObserver(rListSubWin,'$updateEditRecordChanged') Returns FlagOK
Quit method FlagOK
Finally, we need to notify the observers when the thing they are asking to be told about happens.
; Notify the observers.
Do ioChangeRecordObserver.$notify(iList) Returns FlagOK
Quit method FlagOK
A Programmer_Task is availalbe to developer for testing and improving performance of methods.
There are two
items used to interface with the programmer task millisecond timecount functions.If you have a method or series of method you want to check to find out where the greatest performance hit is taking place, do the following.
Do $itasks.Programmer_Task.$logTime($cmethod,'begin')
Do $itasks.Programmer_Task.$logTime($cmethod,'end')
Do $itasks.Programmer_Task.$logTime($cmethod,'begin')
Do $itasks.Programmer_Task.$logTime($cmethod,'begin SQL fetch')
Do List.$getAllRecords() Returns FlagOK
Do $itasks.Programmer_Task.$logTime($cmethod,'end SQL fetch')
If FlagOK
Do $itasks.Programmer_Task.$logTime($cmethod,'begin loop')
For List.$line from 1 to List.$linecount step 1
; Do some stuff.
End For
Do $itasks.Programmer_Task.$logTime($cmethod,'end loop')
End If
Do $itasks.Programmer_Task.$logTime($cmethod,'end')
Quit method FlagOK
This section covers the different types of preferences in StudioWorks, how to get and set them, where they are saved, and how to add your own preferences.
StudioWorks classifies three types of preferences:
The oAppPrefs object class is the interface for getting, setting, and saving app prefs. The main library startup task variable, app_prefs, instantiates the oAppPrefs object class, located in the main library.
Using the oAppPrefs object. Each property method has a getter and setter method.
you can view all the property methods of theWhen you open your application StudioWorks loads the application preferences from one of two locations:
The prefs are loaded into a row variable of the oAppPref object. The row variable is defined using the sAppPrefs_listdef schema classes located in swBase4 and in the main library.
To add your own application preference:
When the oAppPrefs object is initialized it automatically adds getter and setter methods for the new column which you added to the sAppPrefs_listdef schema class in the main library.
The following sample code shows you how to set or get any app pref value.
; Set an app preference.
Do app_prefs.$:developercompanywebsite.$assign('www.vencor.ca')
; Get an app preference.
Do app_prefs.$:developercompanywebsite Returns URL
; Save all app preferences.
Do app_prefs.$savePrefs() Returns FlagOK
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK
The app prefs are saved each time you use the
to do any rebuild, reload, or runtimize operations.constants {
sharedappprefs = TRUE ;
}
Be sure to remember the ; delimiter at the end of the line!
The oLocalPrefs object class is the interface for getting, setting, and saving local prefs. The main library startup task variable, local_prefs, instantiates the oLocalPrefs object class, located in the main library.
Using the oLocalPrefs object. Each property method has a getter and setter method.
you can view all the property methods of theWhen you open your application StudioWorks loads the application preferences from the local_prefs.df1 data file located either in the preferences folder used by the StudioWorks app. The preferences folder is normally in the OMNIS folder, but it could be in the APP folder depending on your startup settings.
Keeping the preferences in the OMNIS folder is recommended so that the user's local preferences will persist even if they replace their entire APP folder.
The prefs are loaded into a row variable of the oLocalPref object. The row variable is defined using the sLocalPrefs_listdef schema classes located in swBase4 and in the main library.
To add your own application preference:
When the oLocalPrefs object is initialized it automatically adds getter and setter methods for the new column which you added to the sLocalPrefs_listdef schema class in the main library.
The following sample code shows you how to set, get, or save any local pref value.
; Set local preference.
Do local_prefs.$:LastUserName.$assign('John Smith')
; Get a local preference.
Do local_prefs.$:LastUserNam Returns UserName
The local prefs are saved each time you close the main library startup task.
You could store module preferences in a special table in the database. An alternate approach used in StudioWorks is to store them in columns of a row variable in the Refs table. Doing so negates the need for creating additional tables in the database for each module and the need for adding columns to the servertable in the database each time you need to add a new preference for the module.
The myModulePrefsDemo library which includes the classes needed to implement the StudioWorks approach to storing module preferences in the columns of a row variable in the Refs table.
demo has aThe mySysAdmin of the StartNewApp demo has an oSysPrefs object class and wSysPrefs window class which you can also review.
The design pattern for module prefs is similar to oAppPrefs and oLocalPrefs. When you want to add a new preference you simply add a column to the applicable sModuleNamePrefs_listdef schema class and rebuild lists.
StudioWorks adds getter and setter propery methods to the oModuleNamePrefs object and you are ready to go!
You can add meta-data for the label and tooltip and then add the edit field to the wModuleNamePrefs window class.
You can directly get any preference settings by instaniating the oModuleNamePrefs object and sending the respective message to the object.
To implement module preferences in one of your libraries do the following:
If you want to have default values for any of the module preferences you can set the default in the appropriate propety method of your module preferences object class.
If isnull(iPrefsRow.ColName)
Calculate iPrefsRow.ColName as 'DefaultValue'
End If
Quit method iPrefsRow.ColName
The Refs server table can be used for storing many different bits of information for use by your application.
Refs is an abbreviation for References. The swRefs4 library is where the various Refs related classes are contained.
Some of the possible uses of the Refs table are:
The primary use of Refs is for edit helper lists to suggest possible entries in a field (Mr., Mrs., Ms., Dr., Sir, Lord,...), or limit the possible entries in a field. (F - Female, M - Male, U - Unknown) In the these are called Refs Lookups.
The oRefs object class is the interface which you should use to access the Refs records. oRefs is instantiated by the main library Startup_Task task variable, refs. To get group/subgroup set of refs records from anywhere in your application you could do the following:
Do refs.$retLookupList(pRefsGroup,pRefsSubGroup) Returns LookupList
If you want to add your own custom methods to oRefs, or wish to modify the behavior of an existing oRef method:
The sRefs schema class lists all of the columns in the Refs table.
The Refs columns of interest are:
As stated previously, the most common use of the Refs table is for edit helper lists.
For example you might have a person table with as a PersonGender column. For consistent data entry you want to give the users 3 options (F - Female, M - Male, U - Unknown).
You don't want to create a special lookup table for Gender, which then requires you to join Person and Gender each time you want to include the person's gender in a list or report. You simply want to stamp M, F, or U in the PersonGender column.
You don't want to hard code the options of F,M,U because your application might be used in a company where English is not the primary language and F,M,U would not be the letters they would use for PersonGender.
The SQL Meta-Data Refs Lookup makes this very easy to implement.
In the auto configure edit window the PersonGender will appear as a lookup field and the user will be able to choose from the 3 options which you entered in the Refs table. If the user types ? in the field a droplist will appear with the following options:
F Female
M Male
U Unknown
Leave the SQL Meta-Data Mandatory checkbox unchecked if you only want to let users choose from a list of suggestions or type any value they want. For example in a NamePrefix field your might want to provide a lookup list that suggests (Mr. Ms. Mrs. Dr. Sir Lord,...) If Mandatory is not checked in the meta-data the user can pick one of the droplist name prefixes or enter their own value. When they leave the field the RefsDisplayText value they picked or other value they entered is what gets stored in the NamePrefix field.
The Refs Lookups are not meant to work as hidden foreign key child/parent table relationship. The Refs Lookups are data entry helpers. The column in the target table gets stamped with the actual refs value which the user can see and edit. Normally the actual Refs actual value is an abbreviation or ID which is meaningful to the users.
The problem with trying to make the refs lookups do "hidden things" behind the scenes is that without a true child/parent - fkey/pkey relationship something is sure to go wrong down the line. You will have a pile of records in a table that are loosely linked to a Refs record and with special code are depending on the loose connection to display the RefsDesc in your window and headed lists. Along comes an unsuspecting System Administrator and they delete the Refs record or change the 'Refs Value' and whamo your edit window, lookup list, and headed lists are dead in the water. The lose connection that was based on the Refs value is lost.
Refs Lookups vs. Child/Parent Table Relationships guidelines:
The alternate solution for #2 is a hard coded droplist or combo-box ... but it seems users always want to change the options, so the Refs lookups are much more flexible solution. They give you the options of droplist or combo-box style editing based on the meta-data Mandatory setting and you can give the user and/or sys admin access to adding/changing the lookup entries.
If it works for the situation - option #2 lets you reduce the number of tiny lookup tables in your database and the number of joins you have to do for lists and reports.Incremental counters are sometimes needed in your application. (eg. Purchase Order numbers, Invoice Numbers, Employee IDs, etc.)
The oRefs object supports incremental counters through the $retNextCounterNum method.
Let's say you have a PurchOrder table with a PONum field. In the method where the user starts a new purchase order you can get the next unique PO number from Refs using just one line of code:
Do refs.$retNextCounterNum('PurchOrder','PONum) Returns NextPONum
If a counter doesn't already exist for PurchOrder/PONum the oRefs object automatically inserts a refs counter record for PurchOrd/PONum with the default value of 1000 and then increments it to 1001. If the record exists, oRefs fetches the record, increments its counter value, updates the record in the database, and if the update succeeds returns the incremented value to the sender.
The oRefs object has its own autocommit session with the database to ensure that counters don't get rolled back. Once a counter has been incremented it can't be rolled back. To do so would cause problems in a multi-user environment.
StudioWorks will automatically set up a counter and use if for a field if you enter [refscounter] as the for a field in the SQL meta-data editor.I find the every time you turn around someone has the need for yet another system preference that needs to be store in the database. Having to add a column to an sSysPrefs schema and then to the table in the database adds to your work and makes it difficult to keep applications in sync with the database. Especially if you have multiple customers with multiple databases.
System preference data types vary. They could be character, date, time, boolean, integer, or other data types.
The Refs table can be use for storing your system preferences. You can insert Refs records with the RefType='syspref' and then set the RefsGroup, RefsSubGroup, RefsDesc, etc. to whatever values you like.
You can create a special qSysprefsList and qSysprefsEdit query class ($extraquerytext = WHERE RefsType='syspref') and declare window instances SysprefsList and SysprefEdit for viewing and editing your own System Preferences.
Any time you need another system preference, you simply add it to the Refs table with the RefType='syspref'.
You may want to create an oSysPrefs object with property methods that fetch the appropriate Refs record(s) through the refs task variable.
Do refs.$retSysPrefsList(TableName) Return SysPrefsList
These are just some ideas and suggestions on how you can use the Refs table for storing your System Preferences.The Refs library is the inspiration of Robert Mostyn. At OmniCamp UK 2004 Robert explained his technique of having a References table for storing all kinds of short lookup lists, user defineable business rules, preferences, etc.
Robert pressed me to implement it in StudioWorks. It took a while for the power of this technique to sink in but as I developed new applications it become clearer to me that a Refs table would be handy in many situations, and flexible.
The decision to put the Refs table into its own swRefs4 library was inspired by the concept used by many Unix programs where they create and use many small programs which have a limited well defined scope of functionality. By keeping the swRefs4 library's scope narrow, it can be more easily implemented in a wider range of StudioWorks applications. At least that's what we're hoping for.
I hope that the swRefs4 library will assist you in more quickly developing your applications and allow them to be more flexible.
Thanks for Robert Mostyn for sharing the Refs table strategy with us.
Doug KuyvenhovenThe oSecurity object is the security guard of your StudioWorks application. oSecurity is instantiated by the main library Startup_Task task variable secur.
When a user signs in to a StudioWorks application, the wSignIn window sends a $signIn(pUserID,pPassword) message to the oSecurity object. The $signIn method searches for the UserID in the list of users and, if found, verifies the password. If the UserID is found and the password matches; information about the user and their security clearances (window instances and schemas) are loaded into the oSecurity object instance and kTrue is returned to the sender. The sign-in process continues and the main window is opened where the user is presented with the navigation treelist of window instances which they are permitted to access.
Sign-in is the first level of security in StudioWorks. The next levels of security in StudioWorks are:
Any user which is declared to be a system administrator has access to all window instances and has full permissions for all schema classes. You do not need to set security for system administrators.
If have an application which does not require security, or a client who does not require security, you can disable StudioWorks security by setting the $:EnforceSecurity property of the oSecurity object to false.
Do secur.$:EnforceSecurity.$assign(kfalse)
Every window instance in a StudioWorks app is declared by the oWindowsList objects. There is one oWindowsList object in each module. The WinInstID must be unique for each window instance.
StudioWorks automatically declares a default list and edit WinInstID for each schema class. For the schema class sAuthor, StudioWorks would declare the WinInstIDs AuthorList and AuthorEdit.
The system administrator has control over which WinInstIDs each user is permitted to access. The navigation treelist only shows WinInstIDs which the user has permission to access.
A user may have access to a window instance, but that doesn't mean the user can edit, insert, or delete records within the window. Those permissions are controlled by schema security.The system administrator has control over which servertables the user is permitted to access in the database. StudioWorks security uses the schema classes which are mapped to servertables. The security control is broken down into the following permissions for each schema class:
The system administrator controls security for users and groups.
Window instances and schema class permissions are set by the system administrator in the
window. In the window you can add or remove users from groups, allow or deny access to window instances, and set permissions for schema classes.Some window instances have a baseschema declared for it in the oWindows list. If access is given to the WinInstID, but view permission is not given to the schema class, a red checkmark will be displayed for the WinInstID access in the window.
It is recommended that a Group. This makes it much simpler to administer security. If a user's position or job function changes they can be added or removed from the applicable groups.
be set up for each type of task or job function and security privileges be set for the , then added to theFrom the StudioWorks developer's point of view, you normally only need to deal with the public interface of the oSecurity object class. The oSecurity object class is instantiated by the main library Startup_Task task variable, secur.
Messages can be sent to oSecurity as needed in your code.
Do secur.$:UserKey Returns UserKey
Do secur.$:UserFormalName Returns FormalName
If secur.$canDelete(BaseSchema)
; Display the 'Delete' button in the toolbar
; or delete the selected records.
End If
You can create groups for purposes other than window instance or schema security. You may need to create a special group for users which are authorized to click an
button on a particular window.You could create an AcceptNewSalesOrders group and add users to this group in the window. When the window instance is opened you could enable/disable the pushbutton based on whether or not the current user is a member of the AcceptNewSalesOrders group.
; Enable/disable the 'Accept Order' button based on whether or
; not the user is a member of the 'AcceptNewSalesOrders' security group.
Do secur.$isMemberOfGroup('AcceptNewSalesOrders') Returns bAuthorized
Do irAcceptOrdersButton.$enabled.$assign(bAuthorized)
There is a wSecurity window which prompts you with a list of users. You select a user and continue. The changeUser method then automatically signs you in using the selected user's ID and password. The menus and window are reinstalled so that you can see exactly what windows the user can access and what menus and toolbar buttons are available to the user.
When you are done, select button on the from the main menu, and sign-in as yourself again.The sSchemaSecurity_listdef defines the schema security list used to keep track of the user and group permissions for all of the schema classes. A series of boolean columns, (canview, canedit, caninsert, candelete, canmultiupdate) indicate the specific permissions.
The schema permissions are normally set for a group. When a user is a member of a group, the user inherits the group's permissions. The user's permission is null if they are inheriting the group's permissions. It is possible to override the group permissions for a specific user (though not recommended).
A user could be given different permissions for the same schema class in different groups which the user is a member of. When this happens the user is given the highest permissions for that schema of the groups which it is a member of. This makes for some pretty complicated code in the oSecurity object. StudioWorks has to loop through all of the groups which the user is a member of, then loop through the schema classes and check the permissions and set each permission to the highest level given for the user.
The list and edit window instances decide which toolbar buttons to display based on the user's permissions for the baseschema of the SQL class being used for the window instance.
If you are writing any security sensitive code use the public interface methods of the oSecurity object class the the secur task variable. You can view all of the method by right-clicking on secur in the task variables pane and selecting the menu line. Each method has a description which you can read in the bottom tab pane of the .There is a security timeout option available with the StudioWorks framework. The timeout option provides an added level of security to a StudioWorks application by opening a timeout window in front of all the other Omnis Studio windows if there is no user activity in the StudioWorks application for a predetermined amount of time. If a user leaves their computer without closing their application, the timeout security will prevent other users from accessing the user's application on their computer after the predetermined amount of inactive time.
Users could get the same type of security on their computer by using a screen saver with password protection. However, that puts control of timeout security in the hands of the users. If enabled, the StudioWorks timeout will enforce timeout security for everyone who has the StudioWorks application open.To enable the security timeout option modify the $signInOKContinue method of the main library Startup_Task to send an $initializeTimeoutTimer message to the oSecurity object followed by a $startTimeoutTimer message.
The following sample code is copied from the initializestartTimeoutTimer method of the Startup_Task of the myAppMain library of the StartNewApp demo.
; Does the user profile, specify a timeout or signoff?
If secur.$:UserTimeoutMinutes.$cando
Do secur.$:UserTimeoutMinutes Returns TimeoutMinutes
Do secur.$:UserTimeoutSignOffTime Returns SignOffTime
End If
; If the timeout minutes is zero, use the default system preference timeout.
If TimeoutMinutes=0
; Use the system prefs default timeout.
If oSysPrefs.$:DefaultTimeoutMinutes.$cando
Do oSysPrefs.$:DefaultTimeoutMinutes Returns TimeoutMinutes
End If
End If
; If the signoff time is null, use the default system preference signoff time.
If isnull(SignOffTime)
If oSysPrefs.$:DefaultSignOffTimeOfDay.$cando
Do oSysPrefs.$:DefaultSignOffTimeOfDay Returns SignOffTime
End If
End If
; Initialize the timeout timer.
If TimeoutMinutes>0¬(isnull(SignOffTime))
If secur.$initializeTimeoutTimer.$cando
Do secur.$initializeTimeoutTimer(TimeoutMinutes,SignOffTime) Returns FlagOK
If FlagOK
; Start the timeout timer.
Do secur.$startTimeoutTimer() Returns FlagOK
End If
End If
End If
Quit method FlagOK
This method is called by $signInOKContinue right after the default method is run.
; Redirect to the startup task default methods object.
Do redirect ioStartupTaskDefaultMethods Returns FlagOK
If FlagOK
Do method initializestartTimeoutTimer Returns FlagOK
End If
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK
The timer is reset each time the user opens a window or switches subwindows, clicks on a toolbar button or a headed list, or presses a key while in an entry field. (You can find all the places where the timeout timer is reset by searching the StudioWorks libraries for Do secur.$resetTimeoutTimer)
If the timer is not reset for the specified number of timeout minutes, the timer is stopped and the wSecurityTimeoutSignIn window is opened. The timeout window opens in front of palette windows, does not allow clicks behind, and disables menus and toolbars. The user must reenter their password in the timeout window. If the user correctly enters their password the timer is restarted and the timeout window is closed allowing them to continue working where they left off. If the user incorrectly enters the password 5 times the timeout window force quits Omnis Studio.You the developer can decide when, where, and how to set the timeout minutes and where to store it.
The practice I normally follow is to have a default timeout number of minutes stored in the system preferences. The default timeout minutes can then set by the system administrator. I also give the option of having a user timeout minutes stored in the user profile. If the user timeout minutes is a non-zero value it is used, otherwise the system preference default timeout minutes is used.
The oSysPrefs object and related wSysPrefs window can be found in the mySysAdmin library of the StartNewApp demo.
Setting the user timeout minutes and signoff time can be found in the wUsrEdit window in the mySysAdmin library of the StartNewApp demo.There is a new password security option available with the StudioWorks framework. The new password option provides an added level of security to a StudioWorks application by checking to see if the user's password has not been changed for a specified number of days. If the password has expired the user is prompted to enter a new password.
There are several security problems with user passwords:
A technique I use to create easy to remember secure passwords is to compose a password sentence that includes at least one number and is easy for me to memorize. For example:
My home is located at 229 Arthur Street.
My password is composed of the first character of each word, and if there are numbers, the full number. So the password for the above password sentence is:
mhila229as
Instead of memorizing the password, you memorize the password sentence. When you need to enter the passord you say the password sentence (silently) and type the first character of each word.
The StudioWorks new password security has several password sentence themes. When a new password is created the date and theme are stored in the user's security info row. When the password expires the user is prompted with the next password sentence theme. The new password window gets the user to input the information need to generate a password sentence, explains it to them, and has them enter the password correctly three times before allowing them to continue and saving the new password to the user's security info row. Hopefully by following this technique, users will commit the password sentence to memory and not need to write down the password.To enable the new password security modify the $signInOKContinue method of the main library Startup_Task to send a $checkPasswordHasExpired message to the oSecurity object. If the password has expired you then send an $openNewPasswordWindow message to the oSecurity object.
The following sample code is the checkPasswordExpired method which can be found in the Startup_Task of the myAppMain library of the StartNewApp demo.
; Get the default password expiry days from the oSysPrefs object.
If oSysPrefs.$:DefaultPasswordExpireDays.$cando
Do oSysPrefs.$:DefaultPasswordExpireDays Returns PasswordExpireDays
If secur.$checkPasswordHasExpired.$cando
; Check if the user's current password has expired.
Do secur.$checkPasswordHasExpired(PasswordExpireDays) Returns bPasswordHasExpired
If bPasswordHasExpired
Do secur.$openNewPasswordWindow() Returns rWin
If isnull(rWin)
Calculate FlagOK as kFalse
End If
End If
End If
End If
Quit method FlagOK
The checkPasswordExpired method is called by the $signInOKContinue method as follows:
; Redirect to the startup task default methods object.
Do redirect ioStartupTaskDefaultMethods Returns FlagOK
If FlagOK
Do method checkPasswordExpired Returns FlagOK
If FlagOK
Do method initializestartTimeoutTimer Returns FlagOK
End If
End If
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK
The oSysPrefs object and related wSysPrefs window can be found in the mySysAdmin library of the StartNewApp demo.
The new password security also makes it possible to give a new user a temporary password which they can can use to sign-in but are then immediately prompted for creating a new password.
The $checkPasswordHasExpired method of oSecurity checks to see if the password is prefixed with temp_. Any password that begins with temp_ (e.g. temp_xzy) is considered to be expired by the $checkPasswordHasExpired method, so the method will return kTrue (yes the password has expired) to the sender. The wSecurityNewPassword window will be opened and the user will be prompted through the steps of creating a new password which will then be save to their user profile replacing the temporary password.
If a user forgets their password, rather than having a system administrator look up and view their password, the system administrator can simply assign a new temp_ password (e.g. temp_dog) and instruct the user to sign-in with the temporary password, following which they will be prompted through creating a new password.
To assign a new password, go to > and edit the user record. Click the button in the edit window. You will be prompted to enter a new password. The prompt message includes instructions on setting a temporary password.