自适应用户管理

Adaptive User Management

我基于 Google 的 "people viewer" 模板构建了一个评论应用程序,允许管理人员为其直接下属创建和编辑评论。

经理链的经理应该可以阅读评论。为此,我创建了一个服务器脚本,假设 EmployeeEmail 将额外存储在评论中。但也许有更好的选择?

function getDirectReportsChainForUser_(query) {
  var userQuery = app.models.Directory.newQuery();
  userQuery.filters.PrimaryEmail._equals = query.parameters.PrimaryEmail;

  userQuery.prefetch.DirectReports._add();
  userQuery.prefetch.DirectReports.DirectReports._add();

  var users = userQuery.run();

  if (users.length === 0) {
   return [];
  }

  var user = users[0];
  var directs = user.DirectReports;
  var records = [];
  for (var i = 0; i <= directs.length; i++) {
    records.push(directs[i].PrimaryEmail);
  }
  // The following lines are based on the asumption that the EmployeeEmail 
  // will be stored in the review in case that there is no better alternative. 
  //The question that then remains is how to recursively add the DirectReports 
  //of the DirectReports to the array???
  var reviewQuery = app.models.Reviews.newQuery();
  reviewQuery.filters.EmployeeEmail._in = records; 
 return reviewQuery.run();
}

经理应该能够定义他的一名或多名副手是否也可以阅读他所在部门的评论。我的想法是通过目录和评论模型之间的多对多关系来解决这个问题,但我不知道如何实现它?

此外,一旦经理或其副手离职,管理员应该可以解除关联并将评论重新关联到继任者。因此,我正在考虑在管理页面中集成多选。这可行吗?

这里我看到至少两个不同的问题:

is there better way to associate directory model's record and ordinary data model than just adding primary email field to the data model

不,目前无法在数据(SQL/Drive 表)和目录模型之间建立关系。

how to recursively get all direct reports for a user

App Maker 的目录模型是 G Suit Admin SDK's Directory API 之上的包装器,仅公开其强大功能的一小部分。当您添加目录模型时,App Maker 会自动插入相应的 Apps Script 高级服务:

由于我们已经配置了 Directory API,我们可以释放它的全部功能,并通过一次调用(如果需要支持分页,则可以多次调用)轻松获取经理的所有下属。为此,我们将使用 Users.List API method with managerId query parameter (the only one that allows us to query all subordinates down the tree). Here are reference for the minimal set of search query parameters quoted from the full search documentation(如果没有这些参数,查询将无法工作或无法以我们需要的方式工作):

  • managerId:用户管理员的 ID,可以是直接的,也可以是管理链上游的 ID。
  • :域名。使用此字段仅从一个域中获取字段。要 return 客户帐户的所有域,请改用 customer 查询参数。必须提供 customerdomain 参数
  • viewType:是否获取用户的administrator-only或domain-widepublic视图。有关详细信息,请参阅 Retrieve a user as a non-administratoradmin_view 是默认值,因此我们需要用 domain_view 覆盖它)。
  • query:用于搜索用户字段的查询字符串。有关构建用户查询的详细信息,请参阅 Search for Users
/**
 * Fetches all reviews associated with all subordinate employees (both direct
 * and indirect reports).
 */
function getAllReportsEmails(managerId) {
  var emails = [];
  var result = AdminDirectory.Users.list({
    domain: 'ENTER HERE YOUR DOMAIN (exapmle.com)',
    query: 'managerId=' + managerId,
    viewType: 'domain_public',
    maxResults: 100
  });

  if (result.users) {
    emails = result.users.map(function (user) {
      return user.primaryEmail;
    });
  }

  return emails;
}


/**
 * Fetches all reviews associated with all subordinate employees (both direct
 * and indirect reports).
 */
function getAllReportsReviewsForManager_(query) {
  var userQuery = app.models.Directory.newQuery();
  // For better security I would recommend to use
  // Session.getActiveUser().getEmail() instead of parameter
  // passed from the client.
  userQuery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();

  var users = userQuery.run();

  if (users.length === 0) {
   return [];
  }

  var manager = users[0];
  var managerId = manager._key;
  var allReportsEmails = getAllReportsEmails(managerId);

  var reviewQuery = app.models.Reviews.newQuery();
  reviewQuery.filters.EmployeeEmail._in = allReportsEmails; 

  return reviewQuery.run();
}

Pavel,我试图将你给我的想法整合到一个服务器脚本中,returns 一组经理和他的整个下属链(直接下属 + 间接下属),这样我就可以使用它需要的时候。我变成了一个递归函数来获取下一个较低级别的直接报告和间接报告。有没有办法得到整个链条?

function getSubordinatesChainForUser(query) {
  var userQuery = app.models.Directory.newQuery();
  userQuery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
  userQuery.prefetch.DirectReports._add();
  userQuery.prefetch.DirectReports.DirectReports._add();
  var users = userQuery.run();
  if (users.length === 0) {
    return [];
  }  

  var userEmails = users.map(function(manager){
    var employeeEmails = manager.DirectReports.map(function(employee){
      return employee.PrimaryEmail;
    });
    return manager.PrimaryEmail + ',' + employeeEmails;
  });

  return userEmails;
}