go to post Eduard Lebedyuk · May 11, 2018 All brokers effectively have Parameter UseSession = 1;But the default value in %CSP.REST is Parameter UseSession As BOOLEAN = 0;So the developer has to remember to override this every time (or sub-class)I recommend having an abstract broker, which does technical stuff like CORS, UseSession, Encoding, JSON transformation. All other brokers must extend it (and they don't do technical stuff, only business logic). More on that.Use same GroupByIdIf two (or more) web applications share the same GroupBy value, then session opened in one application would be valid in all other applications with the same GroupBy value. This way user needs to login only once (or not at all if we have domain/SSO authentication configured). It's also documented (but hard to find), more docs.But if it's a third party app then there is no CSP/ZEN app - the use case I have in mind is a 3rd party web developer is creating a complex shop system that needs to communicate with CachéCSP app could contain only HTML/JS/CSS. So it could be an AngularJS web application, but also hosted with Caché (as a Caché CSP web application).I have no idea or interest in what technology they are using and it may be that their programming language does not easily support cookies so the CSPCHD (the session cookie) does not get passed.If you host a web-application via Caché (Ensemble, HealthShare, InterSystems IRIS) then your web application would be authorization-aware automatically. Browser sends relevant cookies/headers with each request so developer don't need to think about it.I am thinking that in this case the authentication needs to be passed with each Rest call - not an issue(or use OAUTH which I know little about)You can do it like this:Client sends login/pass to some /login REST endpoint and receives tokenAfter that client only sends token with every requestToken should be periodically refreshedThis way you pass login/pass only once instead of with every call. But I'd still recommend Caché security system.
go to post Eduard Lebedyuk · May 11, 2018 Security (link under construction)Using JSON - how do you implement a logon?What are the licensing issues?For password authenticated web applications it is possible by following these steps:All brokers effectively have Parameter UseSession = 1;REST web application and client web application allow only authenticated (i.e. password) access.REST web application and client web application have reasonable Session timeout (i.e. 900, 3600).REST web application and client web application have the same GroupById value.REST web application and client web application have the same cookie path.If all these conditions are met, user would only consume one license slot per session and perform only one login.How do you prevent users hacking restful calls that they have no access to?Authentication as a start, SQL security for basic data access checks, app-level checks for the most specific cases
go to post Eduard Lebedyuk · May 11, 2018 Sessions or No Sessions REST mainly disallows sessions as a mechanism of data transfer. Stateless as stated in REST dissertation by Roy Fielding has three aims:visibilityreliabilityscalabilityVisibility is improved because a monitoring system does not have to look beyond a single request datum in order to determine the full natureof the request. In my opinion that's the most important one and it mainly deals with storing session data in between requests.Let's say you provide a newsfeed API. There's a lot of news so users get them by pages of 10 elements. Clients can access news in two different ways:http://host/api/news/next - in this case the server remembers last page of news the client requested and returns the next one. That's not stateless.http://host/api/news/:pagenmumber - in this case client remembers last page of news he requested and asks for the next one by incrementing page number by 1. That's stateless.Reliability is improved because it eases the task of recovering from partial failures. Where partial failure is defined as (from Waldo J,Wyant G, Wollrath A, Kendall S. A Note on Distributed Computing.):Partial failure is a central reality of distributed computing. Both the local and the distributed world contain components that are subject to periodic failure.In the case of local computing, such failures are either total, affecting all of the entities that are working together in an application, or detectable by some central resource allocator (such as the operating system on the local machine).This is not the case in distributed computing, where one component (machine, network link) can fail while the others continue. Not only is the failure of the distributed components independent, but there is no common agent that is able to determine what component has failed and inform the other components of that failure, no global state that can be examined that allows determination of exactly what error has occurred.In a distributed system, the failure of a network link is indistinguishable from the failure of a processor on the other side of that link.Sessions as an authentication/authorisation mechanism do not affect Reliability.Scalability is improved because not having to store state between requests allows the server component to quickly free resources, andfurther simplifies implementation because the server doesn't have to manage resource usage across requests. Not relevant in our case as Session still gets created, just destroyed immediately after the request is done.To sum up: REST APIs can use sessions as authentication mechanism, but not as a data transfer mechanism.
go to post Eduard Lebedyuk · May 10, 2018 Aletier can now be installed as a plugin, check installation instructions. If you already have eclipse, skip to step 2.
go to post Eduard Lebedyuk · May 10, 2018 Maybe remove $zf calls? Here's sample code: ClassMethod Test() { //Create new Gateway connection object set gc=##class(%SQLGatewayConnection).%New() if gc=$$$NULLOREF quit $$$ERROR($$$GeneralError,"Cannot create %SQLGatewayConnection.") //Make connection to target DSN set pDSN="Cache Samples" set usr="_system" set pwd="SYS" set sc=gc.Connect(pDSN,usr,pwd,0) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 if gc.ConnectionHandle="" W !, $$$ERROR($$$GeneralError,"Connection failed") QUIT set sc=gc.AllocateStatement(.hstmt) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 //Prepare statement for execution set pQuery= "select Name, DOB from Sample.Person WHERE Name %STARTSWITH ?" set sc=gc.Prepare(hstmt,pQuery) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 //Bind Parameters set sc=gc.BindParameter(hstmt,1,1,1,12,30,0,30) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 set var = "A" set sc=gc.SetParameter(hstmt,$LB(var),1) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 //Execute statement set sc=gc.Execute(hstmt) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 //Get list of columns returned by query set sc=gc.DescribeColumns(hstmt, .columnlist) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 //display column headers delimited by ":" set numcols=$listlength(columnlist)-1 //get number of columns for colnum=2:1:numcols+1 { Write $listget($listget(columnlist,colnum),1),":" } write ! //Return first 20 rows set sc=gc.Fetch(hstmt) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 s rownum=1 while((gc.sqlcode'=100) && (rownum<=20)) { for ii=1:1:numcols { s sc=gc.GetData(hstmt, ii, 1, .val) w " "_val if $$$ISERR(sc) break } s rownum=rownum+1 write ! set sc=gc.Fetch(hstmt) if $$$ISERR(sc) break } //Close cursor and then disconnect set sc=gc.CloseCursor(hstmt) if $$$ISERR(sc) w !, $SYSTEM.OBJ.DisplayError(sc) QUIT 0 set sc=gc.Disconnect() quit sc } Check BindParameter method and EnsSQLTypes for SQL types macro definitions. Varchar maybe. You can also try to call PutData method and similar methods (by passing parts of stream there).
go to post Eduard Lebedyuk · May 10, 2018 You can convert object into json: set sc = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(obj) And work with that.
go to post Eduard Lebedyuk · May 10, 2018 You can use zwrite to display object contents to a terminal: set msg = ##class(class).%OpenId(Id) zwrite msg set obj = msg.GetAt(1) zwrite obj
go to post Eduard Lebedyuk · May 10, 2018 So I gather that you HAVE to pass in a list of IDS to exportYes.
go to post Eduard Lebedyuk · May 10, 2018 The problem with write *-3 is that it is currently added to a system code. I'm searching for a better solution.
go to post Eduard Lebedyuk · May 9, 2018 Can you post XML file you're trying to import?Looks like it's empty.
go to post Eduard Lebedyuk · May 9, 2018 #2 limit yourself to 2048 char.Nowadays it's fine. Most browsers work with long URLs.So is your redirect just URL or URL?urplarams=...... It's URL?urplarams=...... One parameter is 5000+ symbols long.
go to post Eduard Lebedyuk · May 9, 2018 I think that using ExportTasks and ImportTasks methods of %SYS.TaskSuper class as proposed by @Sean Connelly and @John Murray would be a better solution as:It would not override system tasksIt would produce readable XML
go to post Eduard Lebedyuk · May 9, 2018 MONEXT is an include file, you can see it in %SYS namespace.You can map it to your namespace (in SMP - Namespaces - Routine mappings).
go to post Eduard Lebedyuk · May 9, 2018 ServerSideRedirect doesn't work in that context (OAuth authentication) unfortunately.I also tried setting LOCATION header directly (via SetHeader method) - in that case I get the same truncated output.
go to post Eduard Lebedyuk · May 9, 2018 You can export/import ^SYS("Task","TaskD") global directly, which contains task definitions data.Some properties are computed (i.e. LastFinished), and could probably cause this error.Try to export/import minimal set of columns.Alternative approach would be writing code to generate tasks.
go to post Eduard Lebedyuk · Apr 27, 2018 export portal settingsWhat settings exactly?Most settings like users, web applications, etc. could be recreated via %Installer (en article, ru article).You can also use Version Control and Continuous Delivery to automate movement between different servers (en articles: 1, 2, 3, 4, 5, 6, ru article covers parts 1 to 4)
go to post Eduard Lebedyuk · Apr 26, 2018 Should they have access?The best solution here is restricting access.InterSystems security model allows for a customizable access management.Application building/testing/deployment tasks could be fully automated and so not require human intervention at all.