UNPKG

google-admin-sdk

Version:

node.js library that wraps the Directory and Groups APIs in the Google Admin SDK

163 lines (147 loc) 7.89 kB
GoogleAPIAdminSDK = require "#{__dirname}/google_api_admin_sdk" _ = require 'underscore' utils = require "#{__dirname}/utils" {Query} = require "#{__dirname}/query.coffee" qs = require 'qs' sanitize = require 'sanitize-arguments' async = require 'async' class OrgUnit extends GoogleAPIAdminSDK # TODO: possibly make customer_id an option of OrgUnit # customer_id, org_unit_path required # if no patch_body is provided, update behaves like get # fields returns only selected properties of an OrgUnit object patch: (customer_id, org_unit_path, patch_body, fields, cb) => arglist = sanitize arguments, OrgUnit.patch, [String, String, Object, String, Function] args = _.object ['customer_id', 'org_unit_path', 'patch_body', 'fields', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.org_unit_path? return die "OrgUnit::patch expected (String customer_id, String org_unit_path, [Object patch_body, String fields, callback])" uri = "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits/#{args.org_unit_path}" uri += "?#{qs.stringify {fields: args.fields}}" if args.fields? opts = { method: 'patch', uri: uri, json: (args.patch_body or true) } q = new Query @, opts return q unless args.cb? q.exec args.cb insert: (customer_id, properties, fields, cb) => arglist = sanitize arguments, OrgUnit.insert, [String, Object, String, Function] args = _.object ['customer_id', 'properties', 'fields', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.properties? return die "OrgUnit::insert expected (String customer_id, Object properties[, String fields, callback])" uri = "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits" uri += "?#{qs.stringify {fields: args.fields}}" if args.fields? opts = { method: 'post', uri: uri, json: properties } q = new Query @, opts return q unless args.cb? q.exec args.cb delete: (customer_id, org_unit_path, cb) => arglist = sanitize arguments, OrgUnit.delete, [String, String, Function] args = _.object ['customer_id', 'org_unit_path', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.org_unit_path? return die "OrgUnit::delete expected (String customer_id, String org_unit_path[, callback])" uri = "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits/#{args.org_unit_path}" opts = { method: 'delete', uri: uri, json: true } q = new Query @, opts return q unless args.cb? q.exec args.cb list: (customer_id, params, cb) => arglist = sanitize arguments, OrgUnit.list, [String, Object, Function] args = _.object ['customer_id', 'params', 'cb'], arglist die = utils.die_fn args.cb return die "OrgUnit::list expected (String customer_id[, Object params, callback])" if not args.customer_id? opts = { json: true } opts.uri = "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits" opts.uri += "?#{qs.stringify args.params}" if args.params? q = new Query @, opts return q unless args.cb? q.exec args.cb get: (customer_id, org_unit_path, fields, cb) => arglist = sanitize arguments, OrgUnit.get, [String, String, String, Function] args = _.object ['customer_id', 'org_unit_path', 'fields', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.org_unit_path? return die "OrgUnit::get expected (String customer_id, String org_unit_path, [, String fields, callback])" opts = { json: true } opts.uri = "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits/#{args.org_unit_path}" opts.uri += "?#{qs.stringify {fields: args.fields}}" if args.fields? q = new Query @, opts return q unless args.cb? q.exec args.cb # get_children takes in a customer_id and org_unit_path and returns the children of that org unit, or an # error if that org unit cannot be found. # Reference: https://developers.google.com/admin-sdk/directory/v1/guides/manage-org-units#get_all_ou get_children: (customer_id, org_unit_path, cb) => arglist = sanitize arguments, OrgUnit.get_children, [String, String, Function] args = _.object ['customer_id', 'org_unit_path', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.org_unit_path? return die "OrgUnit::get_children expected (String customer_id, String org_unit_path, [, callback])" opts = json: true uri: "https://www.googleapis.com/admin/directory/v1/customer/#{args.customer_id}/orgunits" qs: orgUnitPath: args.org_unit_path type: "children" q = new Query @, opts return q unless args.cb? q.exec args.cb # takes customer_id, array of orgunit levels eg. ['CleverStudents', 'Schoolname', ...], and optional cache, and callback # returns callback w/ args orgunit string '/Students/Schoolname' and cache of orgunits created '/', '/Students', '/Students/Schoolname' findOrCreate: (customer_id, org_unit, cache, cb) => if _(cache).isFunction() cb = cache cache = {} arglist = sanitize arguments, OrgUnit.findOrCreate, [String, Array, Function] args = _.object ['customer_id', 'org_unit', 'cb'], arglist die = utils.die_fn args.cb if not args.customer_id? or not args.org_unit? return die "OrgUnit::findOrCreate expected (String customer_id, Array org_unit, [callback])" parent = '/' # for each level in the OU, find that OU or create it and store the response in the cache async.eachSeries args.org_unit, (level, cb_es) => full_path = if parent is '/' then "/#{level}" else "#{parent}/#{level}" if cache[full_path]? parent = full_path return cb_es() @atomic_get_or_create full_path, args.customer_id, level, parent, @, (err, results) -> return cb_es err if err? cache[full_path] = results.body parent = results.parent cb_es err, results.body , (err) -> return die err if err? cb null, parent, cache # use async.memoize for two reasons: # 1. Ensure that the actual find-or-create action is executed at most once. # This avoids a race condition in which the consumer of this library # calls findOrCreate with multiple concurrency # 2. Increases performance atomic_get_or_create: async.memoize (full_path, customer_id, level, parent, that, cb) => async.waterfall [ (cb_wf) => # Make a request to find this OU first. Only make an insert request if the OU doesn't # already exist. that.get customer_id, full_path[1..], (err, body) -> if err? if err.error?.code is 404 and err.error?.message is "Org unit not found" # Not found; pass through to create the orgunit return cb_wf null, null else # A valid error was returned. Return the error and skip the insert. return cb_wf err # If no error, we found the orgunit. Cache it and skip insert because it already exists. # cache[full_path] = body parent = full_path return cb_wf null, { body, parent } (body, cb_wf) => # No need to insert because the org unit was found return cb_wf null, body if body? # Google interface: `name` requires no slash, parentOrgUnitPath requires a slash that.insert customer_id, { name: level, parentOrgUnitPath: parent }, (err, body) => return cb_wf "Unable to create org unit #{full_path}: #{JSON.stringify err}" if err? # cache[full_path] = body parent = full_path cb_wf null, { body, parent } ], cb module.exports = OrgUnit