Scripts in the document
The easiest way to deploy MWScript scripts is to embed them in the document via the document's Scripts window. You can create scripts and UI forms there. You can also import them into the Scripts window from a .mwxml deployment file (which can be exported from the Scripts window of another document).
Scripts that reside in the document can only be modified or enabled/disabled by a user with the Scripting privilege for that document. Users without the scripting privilege cannot disable scripts or prevent them from loading, so it is practical to use scripts to enforce business policies as well as provide extra functionality.
However, having many scripts in a document when they are maintained by external developers can become unwieldy. Either the external developer needs to log into the document to make changes, or an administrative user needs to re-import scripts from a deployment file when the scripts are updated by the external developer.
Loading script packages externally
Prior to MoneyWorks 9.2.3 it was possible to save a collection of scripts and forms into a .mwxml file and reopen them in a standalone script window for editing and testing (if a document is open you get a choice of opening or importing into the document).
There has also long been a .mwblob file format for containing scripts and UI forms. MoneyWorks will auto-load such files from its Autoload folder. A lot of recent MoneyWorks functionality is implemented in MWScript via these files. This format is only available to Cognito.
In MoneyWorks 9.2.3 and later there are two newly available script package formats:
.mwpkg— MoneyWorks binary script collection package — this is a binary format available to everyone for storing scripts and UI objects, together with a code signature.mwpkgd— MoneyWorks script collection directory package — this offers the same features but everything is stored in plain text in a directory (bundle on macOS). It also allows additional support files to be delivered with the package
These packages can be loaded into a document at runtime using the LoadScriptFile function. The package files can be deployed and updated separately from the MoneyWorks document (typically via a package manager script [which will exist eventually]).
These formats have the following properties:
- The contents (scripts, forms) can be cryptographically signed by the author, and the
LoadScriptFilefunction can verify that the contents have not been modified (using the public key provided by the author). This prevents users who do not have the scripting privilege from modifying the scripts and gaining unauthorised access to data thereby. .mwpkgcan optionally be configured to only be openable/modifiable by the author ("closed source")..mwpkgd, being a folder/bundle format has freely readable plain text script files (.mwscript) and UI form files (.mwform, a JSON format). It is always "open source". When being loaded, the contents can still be cryptographically verified to ensure no unauthorised modification. The primary advantage of this format—being plain text—is it is compatible with version control systems such as git. A developer may also choose to edit the scripts using an external editor (signing for deployment must still be performed by the MoneyWorks script editor) [*possible future expansion: allow external editor to reload modified scripts in MoneyWorks; command line tool to update manifest with code signatures]- Whether or not the packages are signed or cryptographically verified is optional, however it should be kept in mind that not doing so will allow any user to execute any MWScript code they choose by simply modifying the file before logging in.
.mwpkgdcan potentially contain other files such as reports. MoneyWorks will ignore files that are not mentioned in the manifest.mwpkgd file that is inside the .mwpkgd folder (the reason it has the same extension as the folder is that Windows does not support the concept of bundle directories, so opening the package requires selecting a file; on Mac, the .mwpkgd appears as a single pseudo-file in the Finder and File Open dialogs). Deployment of .mwpkgd is facilitated by the newUnZip()function (since it would need to be downloaded from a repository as a .zip file)- Some of the standard auto-loaded packages that implement some MoneyWorks functionality are now .mwpkg format. Note that although you can open these packages for access to the source code, modifying them will invalidate the code signature and they will only auto-load at startup when signed by Cognito. If you want to you can load your own modified version explicitly. Doing so will automatically unload the standard version provided the last 3 path components are the same as the originally loaded package (e.g. Scripts/Autoload/Preload_SMTP.mwpkg). Alternatively, you cam explicitly unload the original package with e.g:
UnloadPackage(PlatformStandardPlugInsPath + PATH_SEP + "Scripts/Autoload/Preload_SMTP.mwpkg")(you should do this by adding an additional script at the top of the script list (so that it loads first), that does nothing but unload the original package in itsLoadhandler.
Code Signing
Using external scripting packages hinges on code signing. A standalone script editor window includes a Code Signing Settings... facility, which allows a developer to:
- Create a code-signing private/public key pair. The private key will be kept in their Keychain/Vault and can be selected via its identity name for signing (you can have multiple code signing identities if you wish). You will provide the public key to sites that want to load and verify the signed package. Choose an identity name that is not going to collide with that of other developers who may deploy to the same site.
- Set the package to be automatically signed with a chosen identity whenever it is saved
- Optionally set a signed
.mwpkgto be openable for editing only when the private key is available (do not lose your private key)
If you need to delete unwanted private keys, you will find them in the Mac Keychain Access.app → Passwords, with a name of MWScript_Codesign (the Account name is the identity, and the public key is in the Comment field). On Windows, in Credential Manager → Generic Credentials with "address" MWScript_Codesign/Identity. Although the public key is stored in a comment in the Windows credential record, you cannot see it via the Credential Manager UI.
You can manually enter the credential on another computer (they are standard Ed25519 private/public key pairs in base64 format):
On Mac
- make a new password item (in Keychain Access, not Passwords.app)
- The item name must be exactly
MWScript_Codesign(case sensitive) - The Account Name is the Identity name (also case sensitive)
- The password is the base64 string copied to the clipboard when you originally created the key, or you can retrieve it in Keychain Access
On Windows
- Make a new password item in Credential Manager → Add a generic credential
- The "internet or network address" must be exactly
MWScript_Codesign/your identity name(case sensitive) - The User Name is the Identity name (also case sensitive)
- The password is the base64 string copied to the clipboard when you originally created the key (you cannot retrieve it in Credential Manager)
LoadScriptFile
To load an external package when the user logs into a document, you need a script in the document itself that calls LoadScriptFile, passing the path to the .mwpkg or .mwpkgd and an array containing the identity and public key to verify the code signature. If the script package is to be deployed from a remote repository, it should periodically check the repository for an updated version of the package and download it first as needed. You can download to the standard cache directory and load the package from there.
e.g.
LoadScriptFile("CACHE/MyPackage.mwpkg", CreateArray("My Identity", "kJMl9AQxu4xv-MyPublicKey-+Om8zikk8M="))
Support files
You can store text files in a package that are not MWScript scripts. These may be HTML, javascript, XML etc used as templates or to support a web-based component of a script. A script in the package can load the text into a variable using the GetScriptText function. For better operation with the .mwpkgd format, it is highly recommended to name such files in the package with an extension corresponding to the type of the data (.html, .js, .json, .xml, .md etc). When a "script" is so named, the corresponding file inside the .mwpkgd format will not have .mwscript appended to the name (this behaviour is triggered by the presence of a . in the name).
It is recommended that any developer documentation in the package be placed in a README.txt or README.md file. Documentation.md or Documentation.html should be reserved for user-facing documentation. In future such documentation may be rendered as html for presentation to the user of the package.
Note that a file placed manually inside a .mwpkgd directory will not be added to the list of scripts/resources shown in the Script Editor. You can modify the manifest.mwpkgd text file to include/exclude files that you want to show in the editor and be signed by code signing. Currently the Script Editor does not detect changes made by external editors while the package is open in the MoneyWorks Script Editor. Such changes will be clobbered by saving.