Clarification on Data Permission System

I have a couple questions. First of all I noticed that there’s currently a system role called ServerCodeRunner but I haven’t seen any documentation on it. Is this role auto assigned to code run from business logic?

Second, I started development of my app before that role existed and I’m running into a small problem. Currently whenever I’m going to do something that requires user permissions I do a call to login with the backendless user service. This user currently has a custom role called administrator, which gives it full access to data, messaging, files, etc. However, when I attempt to save an object with backendless data while logged in as that user I get an error saying I don’t have permission to do so.

I’ve attached my current permission setup. Am I doing something incorrectly?

Hello, Benjamin!

First: yes, you’re right. This role defines client type like “REST”, “Android”, “ServerCode” etc.
Second. It looks like a bug on our side. Provide your application ID so we can investigate it.
Thank you!
Alex

Here’s the application id that has the issue: AC51BCD5-F1C6-2CFF-FF70-5C10E7F93100

Thank you for sharing!

We cannot reproduce the issue on your app.
Here is the test we’ve executed:

  1. Create user “test@test”
  2. Assign role “Admin” to created user
  3. Log him in through REST console
  4. Execute POST request to table “<your_table>”
    Please, clarify how exactly you login the user and how the “create” request is being executed. It would be good if you provide a short code snippet that reproduces your problem.
    Also specify SDK you’re using.
    Thanks!
    Alex

Here’s my code directly from intelliJ.

Conversation conversation = new Conversation();
conversation.addEntry(new ConversationEntry(msgArg,
conversation.getEntries().size(), context.getUserId(), context.getUserId()).save());
conversation.save();
This gets run from via the CodeRunner and causes an exception with code 1011 “User has no permission to create entity.”

I’m running Java 8, and my CodeRunner version is 30.0.19

As another side note, all of this code is being run from a custom event handler.

I don’t mean to spam the ticket but there’s a small change to the above code I’ve made as the last parameter in the constructor for ConversationEntry was not needed.
Conversation conversation = new Conversation();
ConversationEntry entry = new ConversationEntry(msgArg,
conversation.getEntries().size(), context.getUserId());
conversation.addEntry(entry.save());
conversation.save();
For clarification the backendContext variable that was previously mentioned. It’s used for calls to some of my event handlers so I can update clients and validate my objects are consistent. This is not a permanent implementation as it’s not the intended use for the event handler class.

For context of the current code seen above, the parameters in the ConversationEntry constructor are: String contents, Integer index, String author in that order. If you need any other clarification please let me know.

You’ve described your case very carefully, thank you. But still I cannot reproduce the problem.
Please, try to execute the following simple code (substitute values in <> to yours):

public static void main( String[] args )
{
  Backendless.initApp( "&lt;APP_ID&gt;", "&lt;SECRET_KEY&gt;", "&lt;VERSION&gt;" );
  Backendless.UserService.login( "<admin@email>", "<adminPassword>" );
  Backendless.Events.dispatch( "&lt;YourCustomEventName&gt;", Collections.emptyMap() );
}

Notify me about results please.
Thank you!

I think I’ve managed to figure out what’s going on, before I do any method calls that require permissions I call a login method I’ve defined that first calls Backendless.UserService.isValidLogin if that returns false then I login. I replaced this with a call directly to login and it seems to work fine now. This does however take more time for the task to complete. Is there any way to keep my server logged in permanently? I’ve tried a call to login with stayLoggedIn set to true in my bootstrap but that login doesn’t seem to persist when an event is triggered.

I’ve also set the permissions for the “ServerCodeUser” role to allow access and modification to most if not all services, however if I remove the login call from my business logic and run the CodeRunner I’m still denied access to save data as well as find Data. If you need more information please let me know.

Thanks for continuing to help!

Code Runner doesn’t store session, I guess that it caused your issue. The requests were executed by not-authenticated coderunner user, hence, it has rejected.
There are two ways to resolve it. The first way you’ve already implemented - it’s about implicit login. The second way is to allow access globally not just for servercode users, but also for not-authenticated. Don’t worry - this configuration wouldn’t allow access for all not-authenticated users. Look how it works: each request to backendless has at least two client roles: one defines if the client is authenticated, and another defines client type. Both these roles has same priority, but if operation is denied for at least one of them - it would be rejected. So, for your case access would be allowed only for not-authenticated servercode requests. If you need access for “admin” user that doesn’t use servercode - then you can still use custom roles. It has higher priority than system roles, so by granting operation for it you’d override restriction on lower level.
Do not hesitate to ask if something is not clear, or my suggestions do not match you idea.
Regards,
Alex

Is it not possible to have anyone login and only have the NotAuthenticated role? That’s really my only concern, as from what I gather my other roles denying access to certain features will take priority over the NotAuthenticated allowing access.

So that would mean for example even if the NotAuthenticated role allows access to create data, the RestUser/AndroidUser role would deny that permission and take priority.

So I’ve done a few things and this is what I’ve been able to do to consistently produce the issue on my end at least.

When I run the following code in the onStart method in my Bootstrap class no issues occur. The entry is saved to the database and everything is fine. However when this code is run directly in the custom event handler I get the User has no permission error. Here’s the code in question,
ConversationEntry entry = new ConversationEntry(" MSG " + new Random().nextInt(1000),
0, “2BC1202D-6A3F-E5AF-FF33-A2621BD5C800”).save();
If you want to see the full event handler or anything else let me know and I’ll upload it to pastebin.

I’ve also attached the current permission setup for the “ConversationEntry” data type.

Is it not possible to have anyone login and only have the NotAuthenticated role?

No, it’s not possible. As I wrote before, each request has at least two roles in context: Auth | NotAuth and client type role.

When I run the following code in the onStart method…

It looks like your custom event is executed by authenticated user without custom roles. When you run request from “onStart()” method - it’s guaranteed that roles set passed to server would be “NotAuthenticatedUser + ServerCodeUser”. However, when a custom event is invoked - roles list contents would depend on request context which invoked the event. For example, if invocation event request has been executed by authenticated android user without any custom roles - then roles list for requests executed from custom handler would be “AuthenticatedUser + ServerCodeUser”. As you see, coderunner would just replace “client type” role.
You can easily check roles list inside custom event by debugging. Put a breakpoint inside your custom event and, when stopped, evaluate the following expression:

context.getUserRoles()

You’ll see the client roles list. Each request to backendless executed from custom handler will have the same list, excluding “client type” role - it would be replaced with “ServerCodeUser” role.

I think I understand, if I allow the Authenticated role the same level as access as the Unauthenticated role then this should work correct?

So I created a breakpoint at context.getUserRoles and as expected I get the roles of the user who triggered the custom event, what I don’t understand is why this would have any effect on the roles of the CodeRunner. When an event is triggered does that cause the CodeRunner to take the same roles as the user that triggered the event?

Yes, you’re almost right.
The only difference is that users “ClientType” role (“AndroidUser”, for example) would be replaced with “ServerCodeUser”.

Are the users custom roles applied as well? With my current setup the custom role assigned to my users only allows them to find objects in a table not create or modify them.

I’d like to keep this the same if at all possible.

Yes, custom roles are also applied.

Is there a way to remove the roles that are assigned to business logic when an event is fired? Or am I going to need to go back to calling login every time an event is fired?

Please, describe your case. I cannot understand what’s meant under “roles assigned to BL”. BL is a role itself, other roles cannot be assigned to it.