Custom Delphi DA Server and Roles

Hello,

Do you have any examples showing how to use roles with a custom Delphi DA server?

Thanks

we have no such example, but I’ll try to describe how it is work:

  • roles are an extension of the session support in Remoting SDK
  • each service or service methods can have roles. role1;!role2 roles means that role1 is allow role and role2 is deny role.
  • in login method, you can assign roles to session via the Session.Roles property.
  • Remoting SDK checks roles before servicemethod is executed and raises correspondent exception if the set of roles prevents execution of service method.

see more at the Roles article.

1 Like

Hi Evgeny,

That’s what I thought. However when I assign roles to Session.Roles I still get an error message:

An exception was raised on the server: Session does not have all the required roles for this action.

This occurs when using the Service Tester app to try out the service.

My service app uses the standard code for login with the addition of the following line:

Session.Roles := [‘ReadSettings’,‘WriteSettings’];

Inside the if aLoginSuccessful then begin block of the LoginServiceLogin method.

I am currently using the latest beta.

Another question I have is how can the client access the session information?

can you send your RODL to support? probably you declared roles in wrong way.
Note: service roles and service method roles are combined during checking access for specific service method.

client can’t access to session information unless you create a custom method which will allow to do this.

There is no RODL file as I am creating a code-first server. Here is the type definition for the service class:


   [ROService]
   TSettingsAPI = class(TRORemoteDataModule)
   public
     [ROServiceMethod]
     [RORole('ReadSettings')]
     function ReadBoolean([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Default: Boolean): Boolean;
     [ROServiceMethod]
     [RORole('ReadSettings')]
     function ReadDouble([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Default: Double): Double;
     [ROServiceMethod]
     [RORole('ReadSettings')]
     function ReadInteger([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Default: Integer): Integer;
     [ROServiceMethod]
     [RORole('ReadSettings')]
     [ROSerializeResultAsUTF8String]
     function ReadString([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         [ROSerializeAsUTF8String] Default: String): String;
     [ROServiceMethod]
     [RORole('WriteSettings')]
     procedure WriteBoolean([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Value: Boolean);
     [ROServiceMethod]
     [RORole('WriteSettings')]
     procedure WriteDouble([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Value: Double);
     [ROServiceMethod]
     [RORole('WriteSettings')]
     procedure WriteInteger([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         Value: Integer);
     [ROServiceMethod]
     [RORole('WriteSettings')]
     procedure WriteString([ROSerializeAsUTF8String] Section: String;
         [ROSerializeAsUTF8String] Key: String;
         [ROSerializeAsUTF8String] Value: String);
   end;

I can’t reproduce this issue.
pls review my testcase: testcase.zip (230.1 KB)

Hi Evgeny,

I had missed adding the CreateSession to the login service’s Login method.

When I call the LoginEx method everything works fine. The next problem I am having is when I try to call the Login method directly to get the UserInfo structure. When I try that I get the following error:

Any additional help would be appreciated.

Thanks

can you create a simple testcase that reproduces this case, pls?

LoginTest.zip (142.6 KB)

Here is what I did for the test:

  1. Create a new custom DA server.
    File|New|Other…
    Delphi Projects|Data Abstract|VCL Application
    Client and a New Custom Data Abstract Server
    PCTrade-SQLite
    (Left defaults for remaining wizard pages, except set Project Name to LoginTest)

2.Converted project to code-first server.Tools|Remoting SDK & Data Abstract|Convert to Code-First Server.
(Waited for conversion to finish.)
3. Added an additional service module to server.
File|New|Other…
Delphi Projects|Remoting SDK|Remoting Code-First Service Module
Change module constant __ServiceName to 'MyService’
Added GetServerString method to service.
Saved service module as MyService_Impl
4. Ran server application and switched back to RAD Studio.
5. Activated client project.
6. Connected client application to remoting server.
Tools|Remoting SDK & Data Abstract|Connect to Remoting SDK Server…
Left defaults and clicked Import button.
7. Added buttons to test LoginEx and Login methods of LoginService.
8. Tried compiling client project. Ran into several errors about missing overload directives and commented out duplicate methods using //todo: comments.
9. Recompiled and ran client project.

LoginEx works as expected.
Login fails with an exception.

thx. this is known issue and isn’t solved yet.

as a temporary workaround, pls include into your server.dpr line:

{$R Shared.res}

shared.zip (1.4 KB)

shared.rodl is fake RODL that helps to generate correct DA types for client-side.

after launching server app, regenerate _Intf from .remoteRODL.
also you need to add DataAbstract4_Intf into uses of client main form

Ok, this solved the stream read error, but now there is a new error.

When the login succeeds, the UserInfo is returned properly. However, if the login fails, and UserInfo is NIL, then the following error occurs:

Error reading parameter aUserInfo: Stream read error

Any suggestions?

A workaround I tried is to create the UserInfo object no matter what and only populate the data into the UserInfo object upon successful login.

By doing so I am returning an empty object instead of a NIL object reference.

can you create a simple testcase, that reproduces this case, pls?
I can’t reproduce this issue with simple testcase like

  r :=  CoLoginService.Create('http://localhost:8099/bin').Login('a','b', v) ;