go to post Ben Spead · Apr 26, 2017 Pravin - nice article, thank you.You might want to add "... using Extended Global Reference" to your Title (to make it easier to find in a search) and include a link to the documentation on that:http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=... Thanks for contributing :)
go to post Ben Spead · Apr 20, 2017 Kyle,The macros are intended to prevent developers from having to refactor code at the same time as they perform an upgrade, as well as make it easier for application providers who have code running on a number of versions.I've learned from experience that it is always best to have the fewest moving parts when possible when doing an upgrade so you can quickly find the cause of any issues that pop up. Therefore, I always try to write forward compatible code and only after all of my systems for a given codebase have been upgraded and are stable do I start to introduce backwards incompatible changes. These macros allow that very nicely. In addition, using the macros means that you have more flexibility to upgrade without having to schedule a concurrent refactoring project (even if it is just a find and replace refactoring project :) ).All that being said, the macros are not intended for long-term use with-in an application. Once the 2016.1 > 2016.2 hurdle has been cleared then my recommendation would be to pull out the macros (find & replace) and stick with Caché's native JSON access going forward. But that can then be a project that takes place post-upgrade, thus simplifying the upgrade and lowering risk.
go to post Ben Spead · Apr 20, 2017 Joe,Better yet, follow the instructions and use the Macros available in the following article (the macros are in a linked Gist code snippet) and then you can write your code in a way that it will work on 2016.1 and also on future versions of Caché without having to rewrite your JSON logic:https://community.intersystems.com/post/writing-forward-compatible-json-...Hope that helps!Ben
go to post Ben Spead · Apr 18, 2017 Fabio - does this work if you make changes via Object access as well, or just SQL?
go to post Ben Spead · Apr 13, 2017 Per #14: Logging - you requested a community Logging solution. Have you seen:https://community.intersystems.com/post/logging-using-macros-intersystems-cach%C3%A9This looks like a very good tool and I am seriously considering standardizing its use in my team.
go to post Ben Spead · Mar 31, 2017 Sven, I know that customers have set this up before. Here are some old notes that I found which may point you in the right direction. NOTE - I have never done this myself so I con't be of much help beyond pointing out this starting point: Implementation Outline: 1. Configure CSP to accept IIS's authentication headers and pass them to Caché 2. Set up delegated authentication to use existing security model to assign $username and $roles based on the user's domain accountname and/or domain groups. (Implement ZAUTHENTICATE.MAC) 3. Enable delegated authentication for any desired services and CSP applications -- in this case the system management portal. · Configuration (e.g. CSP application definition) · Login Page Logic decides based on Gateway Service User, whether to trust REMOTE_USER HTTP header, or to prompt for username/password (other fields such as PIN are also an option). HTH, Ben
go to post Ben Spead · Mar 31, 2017 Steve, Here is some sample code that should help get you going in the right direction. NOTE - the byRef LD argument is a handle for the connection to the LDAP server and it needs to be cleaned up when you're done if you're going to fetch any attributes. (sorry for the messed up indentation) /// Authenticates against the configured domain, with username/password, passing a resulting a status ByRef and a returning success/failure value ClassMethod Authenticate(username As %String, password As %String, ByRef Status As %Status, ByRef LD As %Integer) As %Boolean { Set Status=$$$OK, ret=0 If ('$data(username))||('$data(password)) { Set Status=$$$ERROR($$$GeneralError,"Both fields are required") Quit 0 } Set sc=$$$OK Try { //Connect to the LDAP server Set LDAPServer="myldapserver.mydomain.com" Set sc=$$$OK Set LD=##class(%SYS.LDAP).Init(LDAPServer) If LD=0 { Set LDAPStatus=##class(%SYS.LDAP).GetLastError() Set sc=$$$ERROR($$$GeneralError,"LDAP Init Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } Else { //Authenticate the passed in user by using the Binds command Set Domain=..GetDomain() If ($$$isWINDOWS) { Set LDAPStatus=##Class(%SYS.LDAP).StartTLSs(LD) If LDAPStatus'=$$$LDAPSUCCESS { Set sc=$$$ERROR($$$GeneralError,"LDAP StartTLSs Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } Else { Set LDAPStatus=##Class(%SYS.LDAP).Binds(LD,"",$lb(username,Domain,password),$$$LDAPAUTHNEGOTIATE) If LDAPStatus'=$$$LDAPSUCCESS { Set sc=$$$ERROR($$$GeneralError,"LDAP Binds Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } } } ElseIf ($$$isUNIX) { Set cert = ..GetCert() Set LDAPStatus=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,cert) If LDAPStatus'=$$$LDAPSUCCESS { Set sc=$$$ERROR($$$GeneralError,"LDAP SetOption Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) Do ..RotateOnFailure(sc) } Else { Set LDAPStatus=##Class(%SYS.LDAP).StartTLSs(LD) If LDAPStatus'=$$$LDAPSUCCESS { Set sc=$$$ERROR($$$GeneralError,"LDAP StartTLSs Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } } If LDAPStatus=$$$LDAPSUCCESS { Set LDAPStatus=##Class(%SYS.LDAP).SimpleBinds(LD,username_"@"_Domain,password) If LDAPStatus'=$$$LDAPSUCCESS { Set sc=$$$ERROR($$$GeneralError,"LDAP SimpleBinds Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } } } Else { Set LDAPStatus=$$$LDAPAUTHMETHODNOTSUPPORTED } If (LDAPStatus'=$$$LDAPSUCCESS)&&($$$ISOK(sc)) { Set sc=$$$ERROR($$$GeneralError,"LDAP API Error: "_##class(%SYS.LDAP).Err2String(LDAPStatus)) } } } Catch err { Set sc = $$$ERROR($$$GeneralError,err.Data) } If $$$ISOK(sc) { Set ret = 1 } Else { Set Status = sc } Quit ret }
go to post Ben Spead · Mar 30, 2017 I certainly hope that the mystery parties who have been moderating that site are reaching out to Google in order to get it reinstated. There was certainly a lot of valuable information on that site!
go to post Ben Spead · Mar 29, 2017 See this thread on the Zen Community for a possible starting point:https://groups.google.com/forum/#!topic/intersystems-zen/UI_2fVG9fF0
go to post Ben Spead · Mar 24, 2017 You can use $system.OBJ.Load() or LoadDIr() to load source from disk.
go to post Ben Spead · Mar 23, 2017 Personally, I would do this via Source Control and not via Studio. The approach to this will depend on your source control structures, etc, but the easiest way to handle this for me would be:1) Make sure that everything in my package was checked into my branch, e.g. /MyApp/cls/MyFirstPackage/...2) Since my source tree is structured according to package names, I would copy /MyApp/cls/MyFirstPackage/... to /MyApp/cls/MySecondPackage/... 3) Check in /MyApp/cls/MySecondPackage/... into source control4) Check out /MyApp/cls/MySecondPackage/... 5) Do a Find & Replace in /MyApp/cls/MySecondPackage/... to replace all instances of "MyFirstPackage" with "MySecondPackage"6) Diff /MyApp/cls/MySecondPackage/... and make sure all replacements are desired7) Check in /MyApp/cls/MySecondPackage/... 8) Run my build routine to pull all of /MyApp/cls/MySecondPackage/... into my namespace and Compile it (or just use $system.OBJ.LoadDir() if you don't already have a build routine)Voila! Package is duplicated and all checked into source control ready for further changes :) The above process should only take a couple of minutes.
go to post Ben Spead · Mar 22, 2017 You can use %CSP.StreamServer class. See http://localhost:<your post>/csp/samples/streamserve.csp for a sample showing how to use it.
go to post Ben Spead · Mar 16, 2017 See https://github.com/intersystems-ru/webterminal for a good solution
go to post Ben Spead · Mar 16, 2017 The lock controls the source control hooks, so anything relying on the hooks should prevent changes to items under source control. Parts of the Ensemble Management Portal and the DeepSee portal tie in the hooks for that namespace, so I can see there being a possible interplay there. I have never used the "Deploy Production Changes" utility so I can't say for certain if the source control lock is coming into play there.You should work through this with Managed Services to find a resolution.
go to post Ben Spead · Mar 16, 2017 No - CCR is not a 'released product'. But there are implementation sites partnering with InterSystems that use it.
go to post Ben Spead · Mar 15, 2017 Scott,See the Documatic for the following methods in %Studio.SourceControl.ISC:classmethod Lock(Admin As %Boolean = 0) as %StatusLock the source control hooks for this instance.The default setting will be "Locked". Passing a '1' for the Admin parameter will set the instance to AdminLocked.See Locked for more details.classmethod Locked() as %StringReturns value that shows whether or not this instance is "Locked"Return values are:"": Instance has never been Locked or Unlocked (default)0: Instance is Unlocked1: Instance is Locked2: Instance is AdminLockedWhen the instance is Locked or AdminLocked, no changes can be made via Studio. It is possible to change from Locked to NotLocked via different UIs. When an instance is AdminLocked it should only be possible to unlock it via the Unlock method.classmethod Unlock() as %StatusUnlock the source control hooks for this instance.
go to post Ben Spead · Mar 10, 2017 Andreas - should this be cross-posted on the InterSystems Compatibility blog?http://blog.intersystems.com/compatibility/My guess is that there may be some people who follow that who might miss this significant announcement on the Developer Community. I know I missed this when it was originally posted.
go to post Ben Spead · Mar 10, 2017 You should never do that. That is a stripped down version of apache which should only be used for the Management Portal. You need to install your own full web server
go to post Ben Spead · Mar 7, 2017 Thanks Tim!! Very helpful.One question /comment - your approach doesn't allow for case insensitivity of the http(s)/ftp prefix. I would prefer to set the case insensitivity flag for the whole pattern.According to the ICU documentation (http://userguide.icu-project.org/strings/regexp#TOC-Flag-Options): [quote](?ismwx-ismwx)Flag settings. Change the flag settings. Changes apply to the portion of the pattern following the setting. For example, (?i) changes to a case insensitive match.[/quote]So I was able to make it work as follows: set matcher=##class(%Regex.Matcher).%New("(?i)(\b(https?|ftp)://[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])",string)set string = matcher.ReplaceAll("<a href='$1' target='_blank'>$1</a>") Thanks for the tips and pointing me in the right direction!