Hello,
I am using Kendo for Angular and OpenEdge 11.63
Currently I have 2 services:
1. ...MyApp/static/CrudService.json
2. ...MyApp/static/ReadOnlyService.json
I have 2 separate users:
1. admin with ROLE_PSCAdmin
2. user with ROLE_PSCUser
I separeted their login permissions and user (ROLE_PSCUser) can login only in ReadOnlyService.json and is working.
I don't know how to make the service in the front-end angular project. I am having JSDOSession which is working with one service.
const _serviceURI = 'http://IP:8850/MyApp'; const _catalogURI = _serviceURI + '/static/'+ 'Crud' + 'Service.json';
const _catalogURI2 = _serviceURI + '/static/'+ 'OnlyRead' + 'Service.json'; const authenticationModel = progress.data.Session.AUTH_TYPE_FORM; let opts: progress.data.JSDOSessionOptions = { serviceURI: _serviceURI, authenticationModel: authenticationModel } // create a new session object let _session = new progress.data.JSDOSession(opts); this.jsdoPromise = new Promise((resolve, reject) => { _session.login("username", "password").done(function (_session: progress.data.JSDOSession, result: any, info: any) { console.log("session.login"); _session.addCatalog(_catalogURI).then(() => { console.log("ADMIN"); resolve(self.jsdo = new progress.data.JSDO(self.tableName)); }); }) })
The first Idea I had was to get the ROLE_ from the server but I have no success. I tryed with this:
My second idea is to _session.login() and then to try one by one every _catalogURI and this way to get the user ROLE_, but I have no success as well.
Any suggestions?
Thanks,
Martin
Hello Martin,
Where do you need to know the roles? On the client or on the server?
You can access the ROLES on the server by using GetClientPrincipal().
For the client, you could have an API (invoke operation) that returns the info that the client needs based on the roles, without necessarily providing the roles to the client.
Here is an example of the code you would use on the AppServer:
MESSAGE "DEBUG: REMOTE_USER: " poRequest:GetContextValue("REMOTE_USER").
hCP = SESSION:CURRENT-REQUEST-INFO:GetClientPrincipal() NO-ERROR.
IF hCP <> ? THEN
DO:
MESSAGE "DEBUG: SESSION: USERID: ROLES: " hCP:USER-ID hCP:ROLES.
END.
Documentation: documentation.progress.com/.../index.html
I hope this helps,
Edsel
Hello Edsel,
I am not sure how exactly to use this. Currently I am using oeablSecurity-form-oerealm.xml authentication. I need to see the role of the user on the client. I trying to send the role from back-end application to the browser http header response.
Maybe the way is with implementing getAttribute() in Hybridrealm class, but I don't know how to get and sent the values to the front-end (Angular 4) project.
Hello Martin,
> I need to see the role of the user on the client. I trying to send the role from back-end application to the browser http header response.
Just to confirm, how are you looking to send the roles in the HTTP header response? Are you using a WebHandler based service?
Even though the JSDOSession does not have an API to handle roles on the client side, it has a generic functionality to send properties back and forth to/from the backend using a special HTTP header called X-CLIENT-PROPS.
This functionality is done with APIs setContext(), getContext(), setContextProperty() and getContextProperty().
To use these APIs you would need a backend that works with WebHandlers.
These APIs are currently not documented but I can provide info on them.
Please let me know if you are using one and interested on using this approach.
I hope this helps.
Hello Edgard,
I am using WebSpeed Webhandler with JSDOSession and form-oerealm authentication. In documentation I read there is a getAttribute() in Hybridrealm.cls, but I don't know how to use it.
Hello Edgard,
I am still waiting for your answer.
Hello,
I am sorry that I could not reply earlier. I was not available.
In general, if you need assistance on an issue and you do not hear back, the best would be to contact Technical Support.
> I need to see the role of the user on the client. I trying to send the role from back-end application to the browser http
> header response.
I took a look at the document in $DLC\src\samples\security\OpenEdge\Security\ (BPM_SPAInstructions.pdf) and noticed the description of the getAttribute() method as part of the IHybridRealm interface.
I have not tried it but this seems to provide an attribute on the server side, not on the client side as you need.
Can you use an invoke operation to return the roles to the client?
If you need to return the roles via HTTP header, perhaps, a possible solution for this issue is to use the API that I mentioned earlier that returns the X-CLIENT-PROPS.
I will try to provide info on this API later today.
Thank you and regards.
Hello,
Here is the information on how to return context to the JSDO session using the X-CLIENT-PROPS HTTP header.
To return a custom header when using a WebHandler based Data Service, you would need to register callback handlers to the DataObjectHandler.
To do this you can follow the steps provided in the forum:
https://community.progress.com/community_groups/openedge_development/f/19/p/30896/102961#102961
Note: The files referenced in this post can be found in the attached zip file.
Basically, you would set a program for the session start up to register the callback handlers: session_startup.p.
This program would call a class that performs the actual registration: DOHEventHandler.cls.
The code in the DOHEventHandler.cls file overrides the InvokedHandler and has the logic to set the HTTP header.
The code can look like the following to query the client principal for the roles of the user when a authentication is used to access the Data Service:
hCP = session:current-request-info:GetClientPrincipal() no-error. message "debug: " hCP. if hCP <> ? then do: message "DEBUG: SESSION: USERID: ROLES: " hCP:user-id hCP:roles. poEventArgs:Response:SetHeader(new HttpHeader("X-CLIENT-PROPS", '~{"roles": "' + hCP:roles + '"~}')). end.
The attached zip includes a Business Entity, however, no changes are needed to it. The logic to return the header is done entirely by using the InvokedHandler callback.
Please notice that the header is set only for operations that are performed using the AppServer, i.e., operations such as read, create, update and delete. Operations such as login and addCatalog to access the AppServer.
The following properties need to be set in the oeablSecurity.properties file:
client.login.model=form
OECORSFilter.responseHeaders=Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,X-CLIENT-CONTEXT-ID,X-CLIENT-PROPS
The responseHeaders include X-CLIENT-PROPS so that the client can access the header.
See the oeablSecurity.properties file in the zip file for details.
You may need to restart the PASOE instance to ensure that the new configuration is used.
Once this set up, the X-CLIENT-PROPS header will be returned to the client.
You can use query the HTTP headers of the request to access the X-CLIENT-PROPS header.
Alternatively, you can use the JSDOSession.getContext() or JSDOSession.getContextProperty() to access the context.
Example:
function onAfterFillCustomers(jsdo, success, request) { console.log("DEBUG: fill(): roles: " + request.xhr.getResponseHeader("x-client-props")); console.log("DEBUG: fill(): roles: " + session.getContextProperty("roles")); jsdo.ttCustomer.foreach(function(customer) {
document.write(customer.data.CustNum + ' ' + customer.data.Name + '<br>'); }); }
Note: There is currently an issue where the getContextProperty() would not access the header if the web browser provides the header name in lowercase.
This issue would be fixed in a future version of the JSDO library.
The following links to the JSDO library correspond to JSDO version 4.4.1 with a modification that corrects this issue:
http://oemobiledemo.progress.com/jsdo/progress.jsdo.js
oemobiledemo.progress.com/.../progress.all.js
Please refer to the file test.html in the zip file for a sample program accessing the X-CLIENT-PROPS header.
Please let me know if you have comments or questions.
I hope this helps.
[View:/cfs-file/__key/communityserver-discussions-components-files/17/2502.WebSports.zip:320:240]
Hello,
I noticed that you have post in another forum asking about connecting to a Progress backend from Angular (Angular2):
community.progress.com/.../35606
Are you interested on a general overview on how to connect to an OpenEdge backend or on an overview on the answer to the particular question.
To connect to the OpenEdge backend from a JavaScript client, you can create a REST service that connects to the AppServer and the database.
There are few options to choose from:
- REST by doing visual mapping of the URLs to classes
- REST by using WebHandlers, where the mapping is done programmatically and with a configuration file.
- OpenEdge Data Service: A REST service using prescriptive approach where the mapping of URLs to classes is done automatically. A catalog.json file is generated with the schema and operations of the resources to access from the JSDO, Kendo UI DataSource and Kendo UI Builder.
Once you have enabled the OpenEdge backend for REST access, you can use either an HttpClient API, XMLHttpRequest or the JSDO (JavaScript Data Object) in JavaScript.
Here is a link to a workshop that explains how to create OpenEdge Data Services.
Even though the videos are for working with Mobile from a while back, the concepts are the same.
Check the video for "Exposing OpenEdge Data as REST":
For a simple example using the JSDO, you can take a look at the following example:
oemobiledemo.progress.com/.../example001.html
The following sample program using Angular also help you:
community.progress.com/.../3124
Please notice that this example uses callbacks via subscribe() for async operations.
The JSDO would use use jQuery promises if available.
We have items in our backlog to provide for JavaScript Promises and/or Observable support.
I have also posted this information on the other thread.
Please let me know your have specific questions.
I hope this helps.
Hello Arvind,
You are welcome.
> I am not using Kendo UI or Telerik platform to build web application.
> I am simply using developer studio as IDE with CLI and from here I am trying to connect to OE database and
> want receive values back to the web application based on what I send to OE database.
Thank you for the additional information.
A couple more questions. What version of OpenEdge are you using? Are you using PASOE?
The simplest approach to connect the OpenEdge database and receive values to the web application is to enable REST access via the OpenEdge Data Service approach. This is a prescriptive approach where options to perform CRUD, Invoke and Submit operations are available.
You can use any client to access this service.
(This service type can also be used with the JSDO which then gives you access to Progress technologies that use it.)
An alternative to using the OpenEdge Data Service, would be to enable REST and handle the mapping of URIs to the classes yourself. With this approach you can also add URIs to correspond to an element URI (/service/resource/<id>) in addition to working with a collection URI (/service/resource). The OpenEdge Data Service approach uses collection URIs.
The workshop link that I mentioned earlier provide videos showing how to do this with OpenEdge 11.6.
Even though the workshop was done as part of the Mobile support using the JSDO, the concepts are the same:
- Enable REST access to the OpenEdge backend
- Use a client API to access the REST backend
Please check the following videos in the workshop material:
- Configuring Progress Developer Studio
- Exposing OpenEdge Data as REST
The first video shows you how to create and configure the project in Progress Developer Studio. The second one shows you how to create Business Entity classes to implement the functionality.
Please check the document "Creating an OpenEdge ABL Service using OpenEdge 11.7.0 for information on creating an OpenEdge Data Service:
community.progress.com/.../3363
Here is a summary of the steps (using 11.7.x):
- Create an OpenEdge Project - I will use Sports as an example in the following steps.
- Select Server.
- Specify server:PAS for OpenEdge
transport: WEB
Select Create a Data Object Service
(If you do not have PASOE, select Classic/REST/Create a Data Object Service.)
Follow the wizard using the default values.
Deploy as WebApp: Sports
Make sure that oepas1 is selected in Supported servers.
In the next page, you will see the info for the ABL Service.
Your service name will named <project-name>Service - in my example it is SportsService.
You will also see the format of the URI to access the service.
Specify the database to use by the project.
Open the Servers view.
Notice that the ABL Module Sports and the ABL Service are listed.
Double-click on the oepas1 entry to access a view with details on the server.
Select Open launch configuration.
Specify the database to use by the server.
Start the oepas1 server by using Start from the context menu on oepas1 in the Servers view. (Use right-mouse-click to access the context menu.)
Select AppServer in the Project Explorer and create a Business Entity.
Specify the name of the class. This is the name of the resource. For example "Customer".
For operations select CRUD and Submit.
Select database table Customer.
Click Finish. A Customer.cls would be created. A temp-table with the schema is written to an include file.
Please notice you can change the temp-table and the methods in the Business Entity to match your requirements.
For example, you can remove fields from the temp-table, if you do not want those fields to be returned via REST or you can add fields that are not part of the database table but you want to return to the client. You can set a callback for AFTER-ROW-FILL to populate these fields.
In Project Explorer, Defined Services, do right-mouse-click and use Edit on SportsService. Select Customer.cls to be available via REST.
In the Servers view, notice that service is published and synchronized to oepas1.
Access http://localhost:8810/Sports to check that the service is available.
Access localhost:8810/.../Customer to retrieve values.
Your client code then can use this URL to access the data.
Please create a new thread if you have additional questions.
I hope this information helps you in your project.
Hello Edsel,very intresting post, i have few question around it if i do not disturb you.
i see you are using request.xhr.getResponseHeader("x-client-props")) which is coming from XMLHttpRequest . it has been changed in angular 4, and agular documentation suggests to use HttpClient instead. can you provide some example how rewrite
function onAfterFillCustomers(jsdo, success, request) {
console.log("DEBUG: fill(): roles: " + request.xhr.getResponseHeader("x-client-props"));
console.log("DEBUG: fill(): roles: " + session.getContextProperty("roles"));
jsdo.ttCustomer.foreach(function(customer) {
document.write(customer.data.CustNum + ' ' + customer.data.Name + '
');
});
}
this function to angular 4? i have tried to use HttpClient and after debugging, it returns NULL or Undefined, does that means x-client-props do not transport the role of the user?
if it does and I'm mistaken does user role reaches HTTP header after authentication? or before authentication?
i want to use user role in canActivate guard, so different users can surf over different components. i assume Martin is trying to achieve the same thing.
if you have any useful(Progress recognized practice) suggestion how does surfing is achieved on the client side when using OpenEdge back-end will be interesting to hear.
Hello Edsel,
I am using JSDO 4.3.1 from npm (the last stable version), because 4.4.1 or 4.5 do not have typings and package.json in github. There is a 4.4.0 release for NPM, but it cant be installed trough the terminal.
Martin
Hello Giorgi,
> this function to angular 4? i have tried to use HttpClient and after debugging, it returns NULL or Undefined, does that
> means x-client-props do not transport the role of the user?
> if it does and I'm mistaken does user role reaches HTTP header after authentication? or before authentication?
In the sample code above, the header is returned as part of the execution of an operation that reaches the AppServer. The InvokedHandler event is used.
You would see the header when performing operations such as read, create, update, delete, submit and invoke. Operations such as login and addCatalog to access the AppServer.
To have different users navigate over different components, I would suggest to have a Business Entity that manages this operation. After login, you would call an INVOKE operation to get the roles (or a mapping of the roles) for the user. Notice that with this approach, you would not need to use the x-client-props header.
If you still need to use the approach of using headers, you can use the following code in Angular 4 to retrieve it:
(This example shows the access using BASIC authentication.)
let headers = new HttpHeaders(); headers = headers.append('Authorization', 'Basic ' + btoa('<username>:<password>')); http.get('localhost:8810/.../Customer', { headers: headers, observe: 'response' }).subscribe((response) => { console.log('Response: ', response); console.log('Headers: ', response.headers); console.log('X-CLIENT-PROPS: ', response.headers.get('X-CLIENT-PROPS')); });
I hope this helps.
Hello Martin,
The jsdo NPM package that you are using was provided by community member Lars Neumeier.
We are working on providing an NPM package with the latest JSDO version and up to date typings.
This version would also remove the soft dependency on jQuery Promises.
The NPM branch in GitHub corresponds to our current research / work. Once we have completed the work, the version would be available in the master branch.
Product Management would be able to provide you with info on the roadmap.
I hope this helps.
Thank you egarcia.
Hi Arvind,
Please check the appserver log file. There is an error instantiating your class.
Kind regards,
Daniel.