からめもぶろぐ。

SharePoint が得意なフレンズなんだね!すごーい!

Microsoft Graph の Bookings REST API (Preview) について

Microsoft Bookings という Office 365 Bussiness Premium 向けのサービスがあります。*1

Microsoft Bookings、オンライン スケジューリングおよび予約アプリ

オンラインの予約受付サービスで、顧客はサービスやスタッフ、金額を選択して予約を入れることができ、スタッフはそれを Outlook やモバイル アプリで管理できます。上記のサイトでは、ヘア サロンや金融サービス、不動産業者のデモを見ることができ、予約のプロセスを簡単に確認することができます。

実際に予約ページを開いてみたところ。

カレンダーから担当と時間を簡単に選べます。

とはいえ、デモを見てもわかる通り、予約ページは非常にシンプルなので、カスタマイズしたり、あるいは既存の Web サイトと統合したい、という場合があるかもしれません。あるいは、bot サービスから予約を受け付けたり、予約情報をスタッフで共有するために他のサービスと連携したい、という要望もあるかと思います。そのような場合のために、Microsoft Graph の Bookings REST API を使うことができます。

Customer booking - Documentation - Microsoft Graph

現在プレビューではありますが、Graph Explorer からも試すことができます。v1.0 エンドポイントだと怒られてしまうので、beta エンドポイントに変更するのを忘れずに。

予約 (appointments)、サービス (services)、顧客 (customers)、スタッフ (staffMembers) に対する CRUD 操作ができる他、予約の公開 (publish) または非公開 (unpublish) を行うこともできます。まあだいたいの管理機能は Web の管理画面やモバイル アプリからできるので、あまり使うかというと微妙なところではありますが。

*1:サービスの内容からして中小企業向けですが、エンタープライズ企業 (E3 や E5 を契約している企業) でも使用できます。詳しくは Office 365 Enterprise Edition での Microsoft Booking の有効化 - SharePoint Technical Notes が参考になります。

Microsoft Graph で会議室の予定表を取得する

元ネタ

Graph API 会議室取得の失敗について

結構よくある話で OAuth のハマりどころの最たるものが「アプリケーションにアクセス許可を与えたのにデータが取れない」となることなのです。
上記の「Calendars.ReadWrite.Shared を付けたのに会議室の情報が取れない」というのは、アプリを使用するユーザーに権限がないからで、これはむしろ正しい動作な訳です。「委任されたアクセス許可」という名前が表す通りですね。
公式ドキュメントにも説明があります。

委任されたアクセス許可の場合、アプリの有効なアクセス許可は、アプリに付与されている委任されたアクセス許可 (同意によって付与) と現在サインインしているユーザーの特権が重なる範囲に収まる最小権限になります。

アクセス許可 - ドキュメント - Microsoft Graph

じゃあどうするのというと、代わりに「アプリケーションのアクセス許可」を使うことになります。
ただし、こちらは、バックグラウンドで動作するアプリケーションを想定しているので、気を付けなければなりません。例えば、アクセス許可に「Calendars.Read」を付けると、特定のアカウントだけではなく、すべてのアカウントの予定表が見られるようになります。これはセキュリティ上のリスクが高くなるので、フロントエンドで動作するアプリでの使用は特に気を付けなければなりません。

前置きが長くなったのでサンプル コードです。今回は MSAL を使っています。

using Microsoft.Identity.Client;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

    public static class Program
    {

        private static readonly string TenantId = "<Tenant ID>";
        private static readonly string Authority = $"https://login.microsoftonline.com/{TenantId}/v2.0";
        private static readonly string RedirectUrl = "<Redirect URL>";
        private static readonly string ClientId = "<App ID>";
        private static readonly string ClientSecret = "<App Secret>";
        private static readonly string ResourceId = "https://graph.microsoft.com/.default";
        private static readonly string RequestUrl = "https://graph.microsoft.com/v1.0/users/{0}/calendarView?StartDateTime={1:s}&EndDateTime={2:s}";

        private static void Main(string[] args)
        {
            var userId = "<Resource ID>";
            var startDateTime = DateTime.Today;
            var endDateTime = DateTime.Today.AddDays(1);
            GetCalendarAsync(userId, startDateTime, endDateTime).GetAwaiter().GetResult();
        }

        private static async Task GetCalendarAsync(string userId, DateTime startDateTime, DateTime endDateTime)
        {
            var oauthClient = new ConfidentialClientApplication(ClientId, Authority, RedirectUrl, new ClientCredential(ClientSecret), null, new TokenCache());
            var oauthResult = await oauthClient.AcquireTokenForClientAsync(new[] { ResourceId });
            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", oauthResult.AccessToken);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var responseMessage = await httpClient.GetAsync(string.Format(RequestUrl, userId, startDateTime, endDateTime));
            var responseContent = await responseMessage.Content.ReadAsStringAsync();
        }

    }

}

ちなみに、findMeetingTimes は「アプリケーションのアクセス許可」では動作しないので、こっちを使いたい場合はメールボックスにアクセス許可を付けるしかないですね。

PowerApps PowerShell についてフィードバックを出してみた

ということで PowerApps 用の PowerShell があることを教えていただいたので、ちょっと試してみて困ったところなどをフィードバックしてみました。

powerusers.microsoft.com

Add-PowerAppsAccount でログインするときに IdToken のパターンによってエラーになるケースがあったので。

powerusers.microsoft.com

現状スクリプトを直接ダウンロードなんですが、早く PowerShell Gallery に公開してほしいですね。そのためには現状モジュールの設計もいまいちっぽいので見直しが必要そうですが。

powerusers.microsoft.com

EnvironmentName ってパラメーターなのに GUID なのおかしくない?という話。

スクリプトなのでソース見られるんだけど GitHub で公開してないんでしょうか。全体的にまだまだなのでオープンソースにしたほうがいい気がします。

SharePoint Framework 1.5 がリリースされました

2018/06/05 に SharePoint Framework 1.5 がリリースされました。

developer.microsoft.com

機能追加としては、パッケージ マネージャーとして npm のほかに pnpm と Yarn が使えるようになりました。これによりプロジェクトを作成するときの時間と容量を節約することができるようになりました。軽くベンチマークをとったところ以下のような感じでした。

npm pnpm Yarn
処理時間 (1 回目) 238,031 ミリ秒 192,647 ミリ秒 240,827 ミリ秒
処理時間 (2 回目) 207,439 ミリ秒 95,366 ミリ秒 129,975 ミリ秒
処理時間 (3 回目) 212,534 ミリ秒 103,512 ミリ秒 141,791 ミリ秒
使用容量 338 MB 314 MB 365 MB

Yarn は msi または chocolatey によるインストールが必要ですが、pnpm は npm からインストールできます。お手軽さを考えると pnpm ですかね。

また、プレビュー機能を評価するための plusbeta オプションが追加されました。これにより、通常はプレビュー機能は含まれず、yo で plusbeta オプションを指定した場合のみ利用できるようになります。ただし、これまでプレビューとして公開されている機能 (MSGraphClient など) を使う場合は plusbeta オプションは必要ありません。

そして、プレビュー機能として Dynamic Data が追加されました。これはクラシックの Web パーツ接続に相当するもので、Web パーツ同士でのインタラクティブなデータのやり取りを行うことができます。サンプルとしてリスト アイテムを選択するとリスト アイテムの詳細情報と地図を連動して表示する Web パーツが取り上げられています。

github.com

PowerShell 実践ガイドブック 書籍レビュー

tech.guitarrapc.com

気になったので応募したところ当選してしまいました!ぎたぱそ氏 (@) およびマイナビ出版の方にはこの場を借りてお礼申し上げます。ということで書籍レビューです。


PowerShell との思い出

もともと SharePoint をやってきたので、PowerShell は基本的に SharePoint の管理のためにお世話になっています。SharePoint では 2010 からこれまでの stsadm.exe に代わってサーバー サイドの管理ツールとして SharePoint 管理シェルとして導入されました。*1 最近では SharePoint Online Management Shell だとか PnP-PowerShell だとか、クライアント サイドでの管理ツールも増えてきました。とはいえまだ PowerShell Core には対応されていないので、Windows PowerShell を使っている感じです。*2

SharePoint 以外でも Active Directory の管理や Exchange の管理など、マイクロソフト製品を使っている限りは PowerShell にはお世話になります。かつては ASP.NET から System.Management.Automation.dll を使ってリモートの Exhange に接続して New-MailBox を呼び出すとか無茶なことをしたこともありました。

客先で借り受けた PC に開発環境がなにも入ってなくて、やむなく標準で入っている PowerShell でゴリゴリやったとりか、最悪 .NET が使えるコンパイラ不要な言語として扱えるのでとてもお世話になりました。

Git の CUI としても活躍していますね。posh-git と GitPad の組み合わせがいい感じです。

前置きが長くなったので肝心のレビューをしたいと思います。

よかったところ

動作環境は PowerShell Core が前提です。かなりクロス プラットフォームが意識されており、特にコマンド プロンプトや bash との比較が多かったのが印象的でした。Windows ユーザーはコマンド プロンプトの後継製品としての PowerShell は理解しているはずが、Linux や Mac OS のユーザーにはまだ PowerShell への意識はそんなに高くないと思います。bash との比較があることで、これまでやってきたことやこれからやりたいことが、具体的にイメージできるのではないかと感じました。

PowerShell Core 限定というよりは PowerShell 全般にかかわる内容も多いため、まだ Windows PowerShell を触っている方 (おそらくこっちのほうが大多数のはず) でも役立つ内容がたくさんあります。私は PowerShell を Hey, Scripting Guy! とか個人ブログとか (もちろんぎたぱそ氏のブログも!) を見ながら勉強してきました。やりたいことを満たすための習得にはそれで十分なのですが、それだとやはり知識が偏ってしまうので、網羅的に学習するためにはとてもよい教材だと思います。トランスクリプトとか正直知りませんでした…。知ってたらもっと効率化できたのに!と悔しい思いをしています。

また、経験に裏打ちされたベスト プラクティスが随所に記載されています。個人的には、結果を Write-Output に流さないための書き方のベンチマークは参考になりました。なんとなく PowerShell っぽい書き方で Out-Null を使っていたのですが、パイプラインは時間かかるんですね。これからはほかのやり方で書くことにします。こういったテクニックは第 5 章にまとまっているので、ある程度 PowerShell を知っていて、全部読むのが大変という方は、第 5 章だけでも読むのをお勧めします。

気になったところ

よかったところと相反する形になってしまうかもしれませんが、ほかのスクリプト言語と比較するときにコマンド プロンプトや bash が適当だったかというと、疑問の余地があります。確かに PowerShell は対話型のシェルとして使えるのですが、コマンド プロンプトや bash よりは高級言語の感があるので、比較するなら、Windows であれば VBScript、Linux であれば awk, sed, Perl あたりが比較対象なのかなと。特に VBScript や VBA はパワー ユーザー向けの言語であり、PowerShell への移行が向いているので、これら言語へのサポートがあると、より PowerShell の普及に役立つのではないかと思いました。

細かいところですが、配列のところで固定長の配列を宣言する書き方が言及されていなかったような。特にバイナリの処理でたまに使うので、書いてあると手厚いかなと感じました。

$buffer = New-Object byte[] 1024

誤字がちょっと目立ったのは初版だから仕方ないかなという感じ。改版されることがあれば修正に期待します。

これはもともと本書に期待することではないかもしれませんが、C# との相互運用をもっといろいろ書いて欲しかったです。本書でも C# でコマンドレットを書く方法はありますが、C# から RunSpace を作って PowerShell のコマンドレットを呼び出したりとかできるので、今後そのあたりの本を出してほしいですね!

*1:ちなみにそんな経緯もあって SharePoint 2016 でも管理シェルはモジュール化されておらずスナップインのままです。

*2:PowerShell Core で SharePoint の管理をしたい場合は SPClientCore を使ってね!