Почему коннектор Google Data Studio, который я написал, работает только с моей учетной записью Google? - PullRequest
1 голос
/ 05 августа 2020

Глядя на примеры с открытым исходным кодом, я начал писать свой собственный коннектор Google Data Studio для своего веб-сайта.

Все работает нормально для моей учетной записи google: в редакторе сценариев google я go to publi sh и используйте ссылку для настройки коннектора и посмотрите мои данные в студии данных google.

Когда вы даете ссылку кому-то другому (или просто пытаетесь использовать ее с другой учетной записью Google на том же p c ) Я могу go пройти все шаги, я могу видеть схему и все поля, которые я определил в своем коде скриптов Google, но, нажимая «Создать отчет» или «исследовать», я получаю следующее сообщение об ошибке:

Unknown data source
The data source associated with this component could not be loaded

При нажатии на подробности:

Unknown data source
The data source associated with this component could not be loaded

We were not able to find the data source associated with this component. This can happen when a data source is deleted.

Я вижу в журналах доступа моего API, что URL-адрес, который я определил в функции getData, никогда не вызывается, вызывается URL-адрес isAuthValid (но это вызывается в любом случае перед getData). Я также попытался выбросить исключение в верхней части функции getData, в то время как оно выбрасывает для учетной записи Google, которую я использовал для написания коннектора, другие учетные записи Google, похоже, не заходят так далеко в коде, исключение никогда не генерируется, вместо этого отображается указанная выше ошибка. Я добавил функцию isAdminUser (), которая возвращает true, чтобы включить отладку, но, похоже, не предоставляет дополнительной информации.

Что-нибудь еще, что я могу попробовать, или есть ли какие-либо подробные журналы, которые я могу посмотреть, чтобы увидеть что не так?

Ниже полный файл Code.gs, любой желающий протестировать, это ключ авторизации для тестирования: 954d5fc7-c4b5-404 c -8080-ad5463fca457

var cc = DataStudioApp.createCommunityConnector();
/**
 * Mandatory function required by Google Data Studio that should
 * return the authentication method required by the connector
 * to authorize the third-party service.
 * @return {Object} AuthType
 */
function getAuthType() {
  
  return cc.newAuthTypeResponse()
  .setAuthType(cc.AuthType.KEY)
  .setHelpUrl('https://dashboard.keeperapp.io/settings/google_data_studio')
  .build();
}
/**
 * Mandatory function required by Google Data Studio that should
 * clear user credentials for the third-party service.
 * This function does not accept any arguments and
 * the response is empty.
 */
function resetAuth() {
  var userProperties = PropertiesService.getUserProperties();
  userProperties.deleteProperty('dscc.key');
}
/**
 * Mandatory function required by Google Data Studio that should
 * determine if the authentication for the third-party service is valid.
 * @return {Boolean}
 */
function isAuthValid() {
  var userProperties = PropertiesService.getUserProperties();
  var key = userProperties.getProperty('dscc.key');
  return checkForValidKey(key);
}

/**
 * Checks if the Key/Token provided by the user is valid
 * @param {String} key
 * @return {Boolean}
 */
function checkForValidKey(key) {
  
  var token = key;
  
  var baseURL = 'https://dashboard.keeperapp.io/api/1.0/google_data_studio/' + key + '/checkToken';  
  var options = {
    'method' : 'GET',
    'headers': {
      'Content-Type': 'application/json'
    },
    'muteHttpExceptions':true
  };
  var response = UrlFetchApp.fetch(baseURL, options);
  if (response.getResponseCode() == 200) {
    return true;
  } else {
    return false;
  }
}
/**
 * Mandatory function required by Google Data Studio that should
 * set the credentials after the user enters either their
 * credential information on the community connector configuration page.
 * @param {Object} request The set credentials request.
 * @return {object} An object with an errorCode.
 */
function setCredentials(request) {
  var key = request.key;
  var validKey = checkForValidKey(key);
  if (!validKey) {
    return {
      errorCode: 'INVALID_CREDENTIALS'
    };
  }
  var userProperties = PropertiesService.getUserProperties();
  userProperties.setProperty('dscc.key', key);
  return {
    errorCode: 'NONE'
  };
}


function optionsForDomain(key) {
    var baseURL = 'https://dashboard.keeperapp.io/api/1.0/google_data_studio/' + key + '/getDomains';  
  var options = {
    'method' : 'GET',
    'headers': {
      'Content-Type': 'application/json'
    },
    'muteHttpExceptions':true
  };
  var response = UrlFetchApp.fetch(baseURL, options);
  
  var parsedResponse = JSON.parse(response);
  parsedResponse = parsedResponse.data;
  
  return parsedResponse;
  
  
}
/**
*This turns DEBUG on
*/
function isAdminUser(){
return true;
}

function getConfig(request) {
  var configParams = request.configParams;
  var config = cc.getConfig();
  var userProperties = PropertiesService.getUserProperties();
  var token = userProperties.getProperty('dscc.key');
    
    //create a select item
    var domain = config.newSelectMultiple()
        .setId("domain")
        .setName("Domain");
    
    //get the domains for this key (filled in in the previous step)
    var domainOptions = optionsForDomain(token);
    //transform the array to label and value
    domainOptions.forEach(function(labelAndValue) {
      var domainLabel = labelAndValue[0];
      var domainValue = labelAndValue[1];
      domain.addOption(config.newOptionBuilder().setLabel(domainLabel).setValue(domainValue));
    });
  
  config.setDateRangeRequired(true);
  
  return config.build();
}


/**
* END config
**/

function getFields(request) {
  
  var fields = cc.getFields();
  var types = cc.FieldType;
  var aggregations = cc.AggregationType;
  
  fields.newDimension()
    .setId('domain')
    .setType(types.TEXT);
  fields.newDimension()
    .setId('url')
    .setType(types.URL);
  fields.newDimension()
    .setId('fullPath')
    .setType(types.TEXT);
  fields.newDimension()
    .setId('timestamp')
    .setType(types.YEAR_MONTH_DAY_SECOND);
  fields.newDimension()
    .setId('isMobile')
    .setType(types.BOOLEAN);
  fields.newMetric()
    .setId('performance')
    .setType(types.NUMBER)
  .setAggregation(aggregations.AVG);
  fields.newMetric()
    .setId('accessibility')
    .setType(types.NUMBER)
  .setAggregation(aggregations.AVG);
  fields.newMetric()
    .setId('bestPractices')
    .setType(types.NUMBER)
  .setAggregation(aggregations.AVG);
  fields.newMetric()
    .setId('seo')
    .setType(types.NUMBER)
  .setAggregation(aggregations.AVG);
  fields.newMetric()
    .setId('pwa')
    .setType(types.NUMBER)
  .setAggregation(aggregations.AVG);
  fields.newDimension()
    .setId('report')
    .setType(types.TEXT);
    fields.newMetric()
    .setId('status')
    .setType(types.TEXT);
  
  return fields;
}

function getSchema(request) {
  var fields = getFields(request).build();
  return { schema: fields };
}

function responseToRows(requestedFields, response) {
  // Transform parsed data and filter for requested fields
  return response.map(function(reports) {
    var row = [];
    requestedFields.asArray().forEach(function (field) {
      
      switch (field.getId()) {
           case 'domain':
          return row.push(reports.domain);
           case 'url':
          return row.push(reports.url);
        case 'fullPath':
          return row.push(reports.fullPath);
        case 'timestamp':
          var date = new Date(reports.timestamp*1000);
  var formattedDate = Utilities.formatDate(date, "GMT+0:00", "yyyy-MM-dd HH:mm:ss");
          return row.push(formattedDate);
        case 'isMobile':
          return row.push(reports.isMobile);
        case 'performance':
          num = reports.performance * 100;
          return row.push(parseInt(num));
        case 'accessibility':
          num = reports.accessibility * 100;
          return row.push(parseInt(num));
        case 'bestPractices':
          num = reports.bestPractices * 100;
          return row.push(parseInt(num));
        case 'seo':
          num = reports.seo * 100;
          return row.push(parseInt(num));
        case 'pwa':
          num = reports.pwa * 100;
          return row.push(parseInt(num));
        case 'report':
          return row.push(reports.report);
        case 'status':
          return row.push(reports.status);
        default:
          return row.push('');
      }
    });
    return { values: row };
  });
}

function getData(request) {
  //Note: getData() can return at most 1 million rows/records.
    var userProperties = PropertiesService.getUserProperties();
var token = userProperties.getProperty('dscc.key');
  
  var requestedFieldIds = request.fields.map(function(field) {
    return field.name;
  });
  var requestedFields = getFields().forIds(requestedFieldIds);
  
// Fetch and parse data from API
  var url = [
    'https://dashboard.keeperapp.io/api/1.0/google_data_studio/',
    token,
    '/getReports/',
    request.configParams.domain,
    '/',
    request.dateRange.startDate,
    ':',
    request.dateRange.endDate
  ];
  var response = UrlFetchApp.fetch(url.join(''));
  var parsedResponse = JSON.parse(response).reports;
  var rows = responseToRows(requestedFields, parsedResponse);
   
  return {
    schema: requestedFields.build(),
    rows: rows
  };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...