Hi @Evgeny Shvarov, yes, I had a look at thie project earlier, but my understanding was that it only worked for pure JSON messages and not one that mix classic content with JSON.
- Log in to post comments
Hi @Evgeny Shvarov, yes, I had a look at thie project earlier, but my understanding was that it only worked for pure JSON messages and not one that mix classic content with JSON.
Wish it was so easy. Unfortunately, my challenge is different - DO NOT MODIFY incoming messages but rather create a custom message display handler class. I believe that with some tweaking of standard display handler class and using some advancexd CSS styles, it could be doable.
Hi Enrico,
no magic this time. I just consulted our online documentation, knowing only in advance that $view shows a lot of interesting things :) See this link for details - https://docs.intersystems.com/iris20251/csp/docbook/Doc.View.cls?KEY=RC…
But, you're right, $zname can do the same.
Dan
Excellent!, thank you @Evgeny Shvarov for pointing me at this article. And thank you Stav for great article!
Hello Kris, one of possible approaches might be using a custom query - see Custom Class Queries | InterSystems IRIS Data Platform 2024.1
Dan
call %Library.SQLCatalog_SQLTables()
how about this?
Hi Robert,
indeed it is a bug, that prevents creating a new link. Luckily fix was easy, just to comment a one line of code. I'll give it another try for fix by developers :)
![]()
Hi Evgeny, yes, we do have video recording available. just need to make sure it's good to publish it. it's in Czech language, though.
The link works now.
Hi Eduard, this might be due to the OEX waiting for approval to be published.
Thank you @Nicholai Mitchko for updated information and suggestion. I have modified the article to refer to your reply.
Hi Eduard, I don't think so. There is a trace helper class available in InterSystems IRIS for Health though. But as it is located in HS.HC. package, it is limited just to our healthcare related products.
Hello Nagarjuna,
IAM run on InterSystems IRIS Data Platform 2019.2 and higher. You need to upgrade your server.
Once you're done, you would find everything (the /api/iam application , IAM user) in the System Management Portal.
HTH
Dan
You can also check this link for SOAP debugging - https://community.intersystems.com/post/iscsoap-error-console-log. the first reply in the article points to documentation about SOAP LOG feature - this allows you to record SOAP traffic into a file with all details.
Dan
it turned out to be access privileges issue with license file, what a silly mistake of mine. Anyway, thank you Evgeny for pointing me to some useful info, anyway!
Unfortunately, that did not help. I'll investigate further.
Sebastien,
I remember once customer had the same problem and it turned out that they had large amount of cached queries existent in that namespace.
Can you check and eventually delete them?
Other than this, I can imagine some issues with source control if you have any, but this is just a guess.
HTH
Dan
Zdenek, following up with our offline conversation, I made small change to my installer manifest, so PerformUpgrade() method contains something like this:
s ^dk="Upgrade to version "_..#VERSION_" performed OK"
s ^dk("aux")=pAux
s ^dk("MYVAR")=$System.Util.GetEnviron("MYVAR")
// a nyni muzeme volat kod v manifestu, a nebo taky ne a vse muzeme provest rovnou v teto metode
set pVars("IsUpgrade")=1
set pVars("AppVersion")=..#VERSION
set tSC=..setup(.pVars,3)
return tSC
my simple installer script (CentOS7) - that I sent you offline - needs no changes, but before I call it, I do this:
[root@localhost install-scripts]# export MYVAR="kutac"
[root@localhost install-scripts]# echo $MYVAR
kutac
[root@localhost install-scripts]# ./silent-setup.sh 1
about to run only upgrade
then, looking at %SYS namespace what comes into ^dk global:
[root@localhost ~]# csession ens1
Node: localhost.localdomain, Instance: ENS1
Username: root
Password: ********
USER>zn "%sys"
%SYS>zw ^dk
^dk="Upgrade to version 1.2 performed OK"
^dk("MYVAR")="kutac"
^dk("aux")="toto je test"
%SYS>
--- as you can see, it works just fine. perhaps your problems are due to security / permissions rather then anything else.
feel free to contact me directly.
Dan
So, at the end I found the answer and I'm going to share it with the audience, in case someone may have the same issue.
But before I provide code, a few more words about SOAP service.
The SOAP service has just one method - Test. It accepts a string and returns another string. That's it. I then created a WS Policy via Wizard, this policy is using SAML Authorization with X.509 Certificates. (no ws addressing, no body / token protection, and recipient token using X.509 credentials to keep my example simple)
I then generated a SOAP client, based on WSDL produced by the above service.
and here is the code:
Class WSC.ClientTest Extends %RegisteredObject {/// d ##class(WSC.ClientTest).Run(2) ClassMethod Run(pValue As %String = 0) { set tClient=##class(WSC.SecureDemo.MySecuredServiceSoap).%New() set tClient.SSLConfiguration="SELF-MASTER" /******************************************************************* In real life, we would retrieve a SAML Assertion token from an IDENTITY PROVIDER - IdP - and just pass it to the web service. The WebService (SERVICE PROVIDER / SeP) (unauthenticated or using a technical account on Cache server side) would need to retrieve the SAML Assertion from SOAP Header and perform its validation *******************************************************************/ // !!! PLEASE REMEMBER TO DELETE A WS-POLICY CONFIGURATION GENERATED FOR WS CLIENT! /*********************************************************** * This is a dummy code to construct a SAML token... * ***********************************************************/ set tCred = ##class(%SYS.X509Credentials).GetByAlias("SAML-DEMO","norway01") // Create the SAML Assertion token object - this is just a form of X509 certificate #dim tSamlAssertion As %SAML.Assertion = ##class(%SAML.Assertion).CreateX509(tCred) set tSamlAssertion.IssueInstant = $zdt($h,3,,3) // in real life we would receive this data from IdP !!! #dim tName As %SAML.NameID = ##class(%SAML.NameID).%New() set tName.NameID = "https://DESKTOP-Q224QPV" // saml token issuer, in this case it's me, my computer :) set tSamlAssertion.Issuer = tName set tSub = ##class(%SAML.Subject).%New() #dim tName2 As %SAML.NameID = ##class(%SAML.NameID).%New() set tName2.NameID = "daniel.kutac@intersystems.com" set tSub.NameID = tName2 set tSamlAssertion.Subject = tSub #dim tAuthSt As %SAML.AuthnStatement = ##class(%SAML.AuthnStatement).%New() set tAuthSt.AuthnInstant = $zdt($h,3,,3) // SAML conditions - make sure SAML token is not valid too long... set tNow=$h set tConditions=##class(%SAML.Conditions).%New() set tConditions.NotBefore=$zd($p(tNow,",",1),3)_" "_$zt(($p(tNow,",",2)-30),1) set tConditions.NotOnOrAfter=$zd($p(tNow,",",1),3)_" "_$zt(($p(tNow,",",2)+900),1) set tSamlAssertion.Conditions=tConditions // Attribute statements #define AddAttribute(%key,%value,%nf) set tAttribute = ##class(%SAML.Attribute).%New() ##continue set tAttribute.Name=%key ##continue set tAttributeValue = ##class(%SAML.AttributeValue).%New() ##continue set tAttribute.NameFormat = %nf ##continue do tAttribute.AttributeValue.Insert(tAttributeValue) ##continue do tAttributeStatement.Attribute.Insert(tAttribute) #define AddStringAttribute(%key,%value,%nf) $$$AddAttribute(%key,%value,%nf) Do tAttributeValue.SetString(%value) #define AddElementAttribute(%key,%value,%nf) $$$AddAttribute(%key,%value,%nf) Do tAttributeValue.SetElement(%value) set tAttributeStatement=##class(%SAML.AttributeStatement).%New() $$$AddStringAttribute("name","Daniel Kutac","") $$$AddStringAttribute("network_id","kutac","") $$$AddStringAttribute("division","Sales Organization","") do tSamlAssertion.Statement.Insert(tAttributeStatement) /************************************ * End SAML Assertion data * ************************************/// add SAML Token to SOAP Header do tClient.SecurityOut.AddToken(tSamlAssertion) // add WS timeStamp, this is needed by WS Security policy set tTS=##class(%SOAP.Security.Timestamp).Create() do tClient.SecurityOut.AddSecurityElement(tTS)// this would be, in real life, a technical account, or even unauthenticated CSP application set tUToken=##class(%SOAP.Security.UsernameToken).Create("kutac","xxx") do tClient.SecurityOut.AddSecurityElement(tUToken) // response has - per policy - signed body, we only display result, if signature is valid #dim e as %Exception.AbstractException try { write !," result: ",tClient.Test(pValue) } catch (e) { if $ZERROR["<ZSOAP>" { w !,"SOAP FAULT ERROR:",! d $System.OBJ.DisplayError(%objlasterror) } else { w !,"Other error:",!,e.DisplayString() } } }
one more comment: you may need to implement OnPreWebMethod() method in the SOAP service where you validate incoming SAML assertion token.
Hello Muhammad,
first of all, I'm not able to give you a complete answer, but hope to have some thoughts that may help you.
I'm not an angular nor web developer either, so I have to trust Google, too. According to others (Google) it is indeed difficult to secure information in browser's storage. Besides suggestions like using sessionStorage instead of localStorage, not letting other people to come to your PC and use your open session or ultimately, requiring authentication before each call to resource server, perhaps it might make a sense to pass, together with access token, another parameter in the header, that would change between requests in an exact manner that only resource server and your client know (client using code encapsulation to make it difficult for attacker to find in external files).
Storing access code at the web server app means that you'd need to add to you angular client also something like CSP application or some other server side application. this would make things more complicated to maintain.
Dan
Thank you Michael for spotting this! it's fixed now.
Hello Julie,
AFAIK there is no intelligence in operation's message queue other than First came - first served.
You need to build the logic yourself. Having separate operations for large and small messages / priorities is a good starting point. You can then use poolSize setting to play with priority of processing (bigger poolSize means "usually" larger throughput.)
Dan
For all non-Latin1 sites, this is highly individual and if performed on a long running systems that can not afford (long) interruption, a true challenge. One of our customers (hospital) has done this conversion earlier this year, it took several months to prepare everything, fine tune data migration (they used shadow mechanism to offload data to a Unicode server after initial conversion whilst running the two instances in parallel for testing and validation purposes). Once everything looked ok, and shadow server was in sync with data server, they switched to shadow (Unicode) machine.
Thank you Robert!
Dan
Hi Dmitry,
cool stuff indeed! (much cooler than one I made back in 2007 with plain CSP).
Quick question: would it display contents of large databases (hundreds of GBs) in a readable way too?
Dan
Hello Padma,
sorry for delay in answering, I'm on vacation with limited access to computer. Glad you have resolved the issue!
I was wondering what exactly are you trying to achieve, as grant type is determining messages flow between client and OAuth2 server. The way you authenticate yourself against Cache CSP (client) application is not related to the grant type at all. You can set your client CSP/ZEN app to use any Cache authentication. In one of project, where a Cache is issuing a HTTP request to a OAuth2 protected resource I'm using this code for password type grant:
… main code
try {
set pResponse=##class(User.Response).%New()
set tHttpRequest=##class(%Net.HttpRequest).%New()
$$$THROWONERROR(tSC,..GetAccessToken())
$$$THROWONERROR(tSC,##class(%SYS.OAuth2.AccessToken).AddAccessToken(tHttpRequest,,tSSLConfig,..#oAUTH2aPPnAME,"NOTCSP")) // hardcoded sessionid to NOTCSP
set tHttpRequest.Server=<server>
set tHttpRequest.SSLCheckServerIdentity=0
set tURL=<whatever URL points to the resource>
$$$THROWONERROR(tSC,tHttpRequest.Get(tURL))
#dim tHttpResponse as %Net.HttpResponse = tHttpRequest.HttpResponse
$$$THROWONERROR(tSC,pResponse.Content.CopyFrom(tHttpResponse.Data))
} catch (e) {
Set tSC=e.AsStatus()
}and GetAccessToken method
Method GetAccessToken() As %Status
{
#dim tSC as %Status = $$$OK
try {
//obtain Oauth2 token
set tScope="user/*"
set tApplication=..#oAUTH2aPPnAME
set tSessionId="NOTCSP"
set tUsername=<username>
set tPassword=<password>
#dim tError as %OAuth2.Error
// verify we have already access token
if '##class(%SYS.OAuth2.AccessToken).IsAuthorized(tApplication,tSessionId,tScope,.tAccessToken,.tIdToken,.tResponseProperties,.tError) {
// we shall check whether we have access privileges, not done here
//eventuallyt call ##class(%SYS.OAuth2.Validation).ValidateJWT()
// retrieve token from auth server and store to internal peristent store
$$$THROWONERROR(tSC,##class(%SYS.OAuth2.Authorization).GetAccessTokenPassword(tApplication,tUsername,tPassword,tScope,.tResponseProperties,.tError))
// load token to memory
set tIsAuthorized=##class(%SYS.OAuth2.AccessToken).IsAuthorized(tApplication,tSessionId,tScope,.tAccessToken,.tIdToken,.tResponseProperties,.tError)
}
if $isobject(tError) throw
} catch (e) {
throw e
}
Quit tSC
}This approach has an advantage over usign %GSIZE as the query in %SYS.GlobalQuery class has a parameter that can make quick estimations of the global sizes (simply counting # of blocks occupied by globals) rather than potentialy very slow exact global size determination always used by %GSIZE
indeed, this seems to fix the issue!
Actually, advices given in other answer are quitec contradicting, one says install glassfish whilst other says uninstall glassfish.
Why is Atelier at all trying to use glassfish?