vaadin / collaboration-engine

The simplest way to build real-time collaboration into web apps
https://vaadin.com/collaboration
Other
3 stars 1 forks source link

Add API to check if end user has a seat, registering the seat if needed/possible #11

Closed pekam closed 3 years ago

pekam commented 3 years ago

Because of the licensing model that is based on a monthly end user quota, it is possible that Collaboration Engine features are disabled for a user when the quota is exceeded. By default, the app works as before, but there's no data syncing with CE. For example, CollaborationBinder will continue to work like the regular Binder without field value syncing and field-highlight.

As a developer, I want to know before a user starts using the CE features, whether these features can be enabled for that user, so that I can handle the situation however I want.

Use case

For example, I have a view with a button to start editing a collaborative form. If the user doesn't have CE access, I want to hide the button, so the user can't even open that form.

Solution proposal

Update: see https://github.com/vaadin/collaboration-engine/issues/11#issuecomment-719423671

The solution proposal is a method in CollaborationEngine that takes the user id as an argument and returns a boolean indicating whether the user has CE access for the current month.

Technically, the method just returns true if the user is already assigned to the list of users for this month. Otherwise, it checks whether the monthly quota is full. If there's still room, the user is added to the list and the method returns true. If the quota is full and the user is not in the list, the method returns false. If the grace period is on-going, the quota will be 10x the regular quota.

Usage example

Let's call that method registerUser. The use case above could then be implemented like this:

boolean hasSeat = CollaborationEngine.getInstance().registerUser(userId);
button.setVisible(hasSeat);

API discussion

What should be the method name?

Peppe commented 3 years ago

Out of the list, I think I prefer registerUser. reserveSeat is one alternative that comes into mind.

I also think the parameter should rather be UserInfo than String userId due to you having those around anyhow when adding collaborative features. Or why not both.

pekam commented 3 years ago

As discussed elsewhere, the API needs to actually be asynchronous. When we introduce the clustering support, there will be a network roundtrip for getting the result from the CE server to the application.

The name proposal for now is requestAccess.

The use case sample code would turn into this:

button.setVisible(false);
CollaborationEngine.getInstance().requestAccess(user, hasAccess -> {
    button.setVisible(hasAccess);
});

In practice, it might be a good idea to call requestAccess once when the user logs in, and cache the result.

pekam commented 3 years ago

I also think the parameter should rather be UserInfo than String userId due to you having those around anyhow when adding collaborative features. Or why not both.

It makes sense, that if you anyway need to create the UserInfo, why not pass that as-is. I'm just wondering if there is a situation where you don't want to create the UserInfo yet, but have just the id. Anyway, you could then just call requestAccess(new UserInfo(id), .... But since we're not aware of a real use case like that, I would suggest to avoid bloating the CollaborationEngine API, and adding API only for UserInfo for now. This is not a strong opinion.

heruan commented 3 years ago

To avoid exposing the asynchronous API to the user, we need to take care of that inside the method; to do so, we need to know which UI to access and then we should add a ConnectionContext argument to the signature (plus an overload with a UI argument).

button.setVisible(false);
CollaborationEngine.getInstance().requestAccess(context, user, hasAccess -> {
    button.setVisible(hasAccess);
});