Skip to content

Handle multiple services #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
etatus opened this issue Dec 14, 2020 · 13 comments · Fixed by #258 or #260
Closed

Handle multiple services #256

etatus opened this issue Dec 14, 2020 · 13 comments · Fixed by #258 or #260

Comments

@etatus
Copy link

etatus commented Dec 14, 2020

I can't find a way to connect to more than one service. When you connect a new service, It seems stored data are replaced, so you cannot handle more than one service (access token) at the same time. Is there any way to solve this?

@oshliaer
Copy link
Contributor

Do you use services naming?

OAuth2.createService('drive')
OAuth2.createService('vk')
etc.

@etatus
Copy link
Author

etatus commented Dec 14, 2020

Ok, then OAuth2.createService('name_of_service') not only creates the service but also returns the corresponding auth token object if the service is already created. Is this right?

@erickoledadevrel
Copy link
Contributor

Yes, that's correct. The name of the service is part of the key used to store and retrieve tokens.

@etatus
Copy link
Author

etatus commented Dec 14, 2020

Ok, thank you. I guess the library doesn't provide the list of created services, so a possible way to do that would be:

var keys = userProperties.getKeys();
var services_names = Array();
for (var i = 0; i < keys.length; i++) {
        if ( keys[i].indexOf('oauth2.') === 0 ) services_names.push( keys[i].split('oauth2.')[1] );
}

Is there a more "ellegant" way to do this? Maybe could be an interesting feature to add to the library.

@erickoledadevrel
Copy link
Contributor

Ya, that could be something we add to the library. How would you use that function though? In my experience most often the services are more fixed and known to the script.

@etatus
Copy link
Author

etatus commented Dec 14, 2020

In my case, I need to show all the connected services to the user and give him/her the option of adding more or disconnecting them (individually). For instance, Stripe handles different accounts with a single user that would correspond to different services.

In general, I guess this make sense when you have to keep several services connected (Stripe accounts in my case) because the user is going to use them frequently.

@etatus
Copy link
Author

etatus commented Dec 14, 2020

BTW, a very simple way to facilitate the manage of multiples services is that the library store them under the same property, as a list of service objects. In this way, you only need to read one property (let's say oauth2):

var services =  userProperties.getProperty( 'oauth2' );

// Result: { 'service_name1':serviceObject1, 'service_name2':serviceObject2 }

@erickoledadevrel
Copy link
Contributor

I've added OAuth2.getServiceNames(propertyStore) for this purpose. Since service can be saved to different types of properties you need to pass in the store. I've not used a single property to track them, as that could run into concurrency issues, but filtering the properties is simple and performant enough.

@etatus
Copy link
Author

etatus commented Dec 15, 2020

Thank you! This function helps a lot in handling multiple services.

Just one important question: the more recent service is the first one (index 0) or the last one in the service names array returned by the function?

@erickoledadevrel
Copy link
Contributor

The function doesn't make any guarantee about the order of the returned services. However you could encode the creation date in the service name (for example stipe_20201215T123000) or setting it as a custom property in the service's storage:

function authCallback(request) {
  var service = getService();
  var authorized = service.handleCallback(request);
  if (authorized) {
    service.getStorage().setValue('creation_date', (new Date()).toISOString());
    return HtmlService.createHtmlOutput('Success!');
  } else {
    return HtmlService.createHtmlOutput('Denied.');
  }
}

@etatus
Copy link
Author

etatus commented Dec 15, 2020

Hmmm that's not good news. I'd expect the library (and the function) could guarantee the correct order of the services.

I have 2 ideas I hope you can consider that could solve the problem:

  1. To manage the storage of services as an array in an unique property so the library just push() new services and splice() the deleted ones. Thus, OAuth2.getServiceNames() will always return a sorted array of service names.

  2. To include a timestamp internally as part of the property of each service in a way OAuth2.getServiceNames() and return the correct order and optionally the timestamps (this would be awesome!).

var timestamp = new Date().getTime();
var service_property = 'oauth2.'+timestamp+'.'+service_name;

var timestamp = service_property.split('.')[1];

@erickoledadevrel
Copy link
Contributor

I don't think it makes sense to implement ordering in the library, given the methods I outlined for implementing it yourself and that this is a fairly niche feature.

@etatus
Copy link
Author

etatus commented Dec 15, 2020

Sorry, I guess I disagree. It's quite strange for me that the items of an array returned by a function could be in different positions everytime you call it without any criteria (this is computer science!). I'm not telling that the order has to be necessarily the creation timestamp, but at least the criteria should be known in order to get more deterministic results.

Thank you anyway for your amazing library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants