Google Apps APIで新入社員対応(ユーザー追加+組織・グループに追加)

こんにちは井上です。
Google Appsでユーザーを追加する時って、大抵の場合グループにもそのユーザを参加させると思うんです。グループ管理は煩雑になりやすく、役割が重複したものやメンバーの差異がほとんどないものなど、数多くのグループが作られがちです。ですので1ユーザーは複数グループに追加する必要が出てきますが、Google AppsGUIを使ってグループにユーザーを追加しようとすると非常にめんどくさい!

という訳でGoogle Apps APIをたたいてユーザ追加と同時にグループに参加させるようにしてみました。ついでに組織にも所属させるようにしました。普通はGoogle Apps Scriptからやると思いますが、敢えてC#で。

なお、ユーザー削除時はユーザーを削除すればそのユーザーが属しているグループからも勝手に消えるのでGUIで困ってません。ユーザー削除が頻繁にあるなら別ですが、それって会社としてどーなのって感じですし(´・ω・`)

ご丁寧に公式にお手軽スタートマニュアルが用意されています。
.NET quickstart  |  Directory API  |  Google Developers

APIドキュメントはこちら。
Admin SDK: Directory API  |  Google Developers

Google APIs Client Libraryをインストールします。 f:id:ihisa:20160401100908p:plain

簡単なフォームを作ります。(Google Appsのユーザー追加画面風)
f:id:ihisa:20160404134408p:plain

コードは以下の通り。
ちょっと気を付けなければいけないポイントは以下ぐらいです。

  • 組織はUser.OrganizationじゃなくてUser.OrgUnitPathで指定
  • パスワードはポリシーに従った値でないとHTTPステータス400になります。
  • グループ一覧取得時はCustomerプロパティ値を指定しないとHTTPステータス403になります。
using Google.Apis.Admin.Directory.directory_v1;
using Google.Apis.Admin.Directory.directory_v1.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace GoogleAppsManagement
{
    public partial class Main : Form
    {
        UserCredential credential;
        DirectoryService service;
        static string applicationName = "GoogleAppsApplication";
        static string customer = "my_customer"; // この文字列を指定すると実行者のcustomerIdが取得されます。
        static string domain = "@sanwasystem.com";
        IList<OrgUnit> orgunits;
        IList<Group> groups;

        public Main()
        {
            InitializeComponent();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            // UserCredentialの作成
            this.CreateUserCredential();
            
            // DirectoryServiceの作成
            this.CreateDirectoryService();

            // 組織の取得。ここでは組織名称を表示しています。
            orgunits = this.GetOrgunits();
            this.OrgUnitList.DataSource = orgunits.Select(x => x.Name).ToList();

            // グループの取得。ここではグループアドレスを表示しています。
            groups = this.GetGroups();
            this.GroupList.DataSource = groups.Select(x => x.Email).ToList();
        }

        private void AddUser_Click(object sender, EventArgs e)
        {
            string mailAddress = this.mailAddress.Text + domain;

            // ユーザ追加
            User user = new User();
            user.Name = new UserName()
            {
                FamilyName = this.FamilyName.Text,
                GivenName = this.FirstName.Text
            };
            user.PrimaryEmail = mailAddress;
            user.Password = this.Password.Text;
            user.OrgUnitPath = orgunits.Where(x => x.Name == this.OrgUnitList.SelectedValue.ToString()).First().OrgUnitPath; // 選択した組織のOrgUnitPathを指定
            UsersResource.InsertRequest requestUser = service.Users.Insert(user);
            var responseUser = requestUser.Execute();
            
            // グループに追加
            foreach(var row in this.GroupList.SelectedItems)
            {
                MembersResource.InsertRequest requestMember = service.Members.Insert(
                    new Member()
                    {
                        Email = mailAddress,
                        Role = "MEMBER", // 役割。MANAGER / MEMBER / OWNER
                        Type = "USER" // メンバータイプ。CUSTOMER / GROUP / USER
                    },
                    row.ToString()  // グループのIDかメールアドレスを指定なのでメールアドレスを指定しています。
                    );
                var responseGroup = requestMember.Execute();
            }
        }

        private void CreateUserCredential()
        {
            // https://console.developers.google.com/project
            // Google API Consoleからあらかじめ発行したクライアントIDのJSONファイルを指定します。
            // これにより、プロジェクトを実行するとブラウザが立ち上がり認証が行われます。
            using (var stream = new FileStream("client_id.json", FileMode.Open, FileAccess.Read))
            {
                string credPath = System.Environment.GetFolderPath(
                    System.Environment.SpecialFolder.Personal);
                credPath = Path.Combine(credPath, ".credentials/admin-directory_v1-dotnet-quickstart.json");

                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new string[]{ 
                        // 実行したい処理に合わせてスコープを指定します。
                        DirectoryService.Scope.AdminDirectoryGroup,
                        DirectoryService.Scope.AdminDirectoryGroupMember,
                        DirectoryService.Scope.AdminDirectoryUser,
                        DirectoryService.Scope.AdminDirectoryCustomer,
                    },
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;
            }
        }

        private void CreateDirectoryService()
        {            
            service = new DirectoryService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = applicationName, // 値は何でも良い
            });
        }
        
        private IList<OrgUnit> GetOrgunits()
        {
            OrgunitsResource.ListRequest orgunitsResourceRequest = service.Orgunits.List(customer);
            return orgunitsResourceRequest.Execute().OrganizationUnits;
        }
        
        private IList<Group> GetGroups()
        {
            GroupsResource.ListRequest groupsResourceRequest = service.Groups.List();
            groupsResourceRequest.Customer = customer;
            return groupsResourceRequest.Execute().GroupsValue;
        }
    }
}

Google AppsGUIは微妙ですがAPIは充実していますので、自分たちで便利にしていけばいいですね!