ぼーっとしてたら月が替わってしまったのですが、2021/02/19 に Power Apps オンライン勉強会に登壇しました。
スライドは Speaker Deck にアップロードしています。
Power Apps 勉強会にもかかわらず半分以上スクラムの話をしているというハードな内容で申し訳ありませんでした。ただ、スクラムではなくても、アプリの ALM を考えることは大事だと思いますので、単に作ればいいというのではなく、リリースしたあともアプリを育てていくことを考えていただければと思います。
ぼーっとしてたら月が替わってしまったのですが、2021/02/19 に Power Apps オンライン勉強会に登壇しました。
スライドは Speaker Deck にアップロードしています。
Power Apps 勉強会にもかかわらず半分以上スクラムの話をしているというハードな内容で申し訳ありませんでした。ただ、スクラムではなくても、アプリの ALM を考えることは大事だと思いますので、単に作ればいいというのではなく、リリースしたあともアプリを育てていくことを考えていただければと思います。
今まで Azure Active Directory のアプリケーションはいつも Azure Portal から作っていたのですが、展開するときにコード化されていないと困るので、やる方法をまとめてみました。いくつか方法があって苦労したので雑にまとめておきます。
New-AzureADApplication を使ってアプリケーションを作成することができます。
使ってみたところ以下の問題点がありました。
New-AzADApplication を使ってアプリケーションを作成することができます。
使ってみたところ以下の問題点がありました。
az ad app create を使ってアプリケーションを作成することができます。
使ってみたところ以下の問題点がありました。
New-MgApplication を使ってアプリケーションを作成することができます。
使ってみたところ以下の問題点がありました。
とりあえず Microsoft.Graph モジュールがよさそう。
前回の記事では Microsoft Teams Toolkit を使ってアプリを実行するまでの手順を確認しました。
記事中にも説明した通り、Microsoft Teams Toolkit の既定の言語は JavaScript です。しかし、モダン開発を行う上で TypeScript を使うことは必須とも言えます。そこで、Microsoft Teams Toolkit で作成したプロジェクトで TypeScript を扱うことができるようにしたいと思います。
JavaScript の拡張子である .js ファイルを TypeScript のものに変更します。通常の TypeScript の拡張子は .ts ですが、React の JSX を扱う場合は拡張子は .tsx となります。以下のファイルの拡張子を変更します。
React の標準パッケージを型解決できるように型定義パッケージをインストールします。
npm install @types/react @types/react-dom @types/react-router-dom --save-dev
TypeScript のパッケージをインストールします。
npm install typescript
TypeScript のトランスパイルには tsconfig.json が必要なのですが、初回に npm run start したときに自動的に生成されますので、いったんはそのままで問題ないです。
Tab.tsx が型解決できずにエラーになるので修正します。
React のコンポーネントには Props と State がありますがこれを interface で定義します。
interface ITabProps { } interface ITabState { context: microsoftTeams.Context }
コンポーネントの継承をジェネリックになるように変更します。
class Tab extends React.Component<ITabProps, ITabState> { ... }
コンストラクタでは型を指定するようにします。
constructor(props: ITabProps) { super(props) this.state = { context: {} as microsoftTeams.Context } }
microsoftTeams.getContext のコールバックが定義と合わずにエラーになっているのでパラメーターの error を削除します。
componentDidMount() { microsoftTeams.getContext((context) => { this.setState({ context: context }); }); }
これで npm run start すればコンパイルが成功するはずです。ちなみに、そもそも React ではクラス コンポーネントではなく関数コンポーネントを使うようになってきていますので、まるっと書き直してしまったほうが速いかもしれません。さっくりと書き直した場合、こんな感じになります。
import React from 'react'; import './App.css'; import * as microsoftTeams from "@microsoft/teams-js"; const Tab: React.FC = () => { const [context, setContext] = React.useState<microsoftTeams.Context>(); const [userName, setUserName] = React.useState<string>(); React.useEffect(() => { microsoftTeams.getContext((value) => { setContext(value); }); }, []); React.useEffect(() => { if (context) { setUserName(Object.keys(context).length > 0 ? context['upn'] : ""); } }, [context]); return ( <div> <h3>Hello World!</h3> <h1>Congratulations {userName}!</h1> <h3>This is the tab you made :-)</h3> </div> ); } export default Tab;
Teams アプリの開発をこれから始めるというときに環境構築のための機能がいくつか提供されています。
Yeoman ジェネレーターについては Microsoft Learn で使用方法が説明されています。
Global Microsoft 365 Developer Bootcamp でもお話しさせていただきました。
もう一つの Microsoft Teams Toolkit での Teams アプリについて、Yeoman ジェネレーターとの違いや、実際に構築してみてのハマリどころをまとめてみたいと思います。
どちらも React を使ったアプリを構築できるという点では同じですがいくつかの相違点があります。
Yeoman ジェネレーター | Microsoft Teams Toolkit | |
---|---|---|
言語 | TypeScript | JavaScript |
タスク ランナー | gulp | react-scripts |
ngrok | あり | なし |
Yeoman ジェネレーターのほうがいろいろ親切ではありますが、Microsoft Teams Toolkit は create-react-app で作ったのに近い構成になるため、React に慣れている人には扱いやすいです。個人的には、よりシンプルな Microsoft Teams Toolkit で始めるのをお勧めしたいです。
Microsoft Teams Toolkit は Visual Studio Code の拡張機能です。なのでまずは Visual Studio Code で拡張機能をインストールします。
インストールするとアクティビティー バーに Microsoft Teams のアイコンが追加されるのでクリックします。[Create a new Teams app] をクリックします。サインインを要求されるので Teams アプリをホストするテナントのアカウントでサインインします。
[Tab] を選択して [Next] をクリックします。
[Finish] をクリックします。ワークスペースの保存先を聞かれるので任意のフォルダーを選択します。
ワークスペースが Visual Studio Code で開きます。
ターミナルで以下のコマンドを実行します。
npm install npm run start
デバッグを開始するとブラウザーが起動します。*1
[追加] をクリックします。
アプリが表示されるはずですが、実は表示されません。これは localhost を HTTPS で起動しているのに証明書が正しくないことが原因です。なので自己証明書を作成してエラーが出ないようにする必要があります。
Windows PowerShell (PowerShell 7 では駄目です) を管理者として起動し以下のコマンドを実行します。
New-SelfSignedCertificate -Subject "localhost" -DnsName "localhost" -NotAfter "2099/12/31" -CertStoreLocation "cert:\CurrentUser\My"
作成した証明書を秘密キーをつけて pfx ファイルとしてエクスポートします。
エクスポートした pfx ファイルを [信頼されたルート証明機関] にインポートします。
OpenSSL を使って以下のコマンドを実行します。
openssl pkcs12 -in localhost.pfx -nocerts -nodes -out localhost.key openssl pkcs12 -in localhost.pfx -clcerts -nokeys -out localhost.crt
ワークスペースに cert というフォルダーを作成して localhost.key と localhost.crt をコピーします。.env ファイルに以下を追加します。
SSL_CRT_FILE=./cert/localhost.crt SSL_KEY_FILE=./cert/localhost.key
パラメーターの意味については公式ドキュメントを参照してください。
さてこれで準備ができたので再度 npm run start を実行しデバッグを開始します。
表示されました!
よく Teams アプリの開発をするときに「ngrok は必須です」という話を見ますが、見ていただいたとおり必須ではなく、localhost でも実行可能です。ただし、HTTPS であることは必須なので、今回の手順のように自己証明書を用意するか、ngrok を使うということになります。ただ Microsoft Teams Toolkit の場合、ngrok だと URL がランダムになってしまうので大変かもしれません。Yeoman ジェネレーターはそのあたりよろしくやってくれます。
*1:うまくいかない場合は Visual Studio Code の Debugger for Chrome や Debugger for Microsoft Edge がインストールされていない可能性があります。
Microsoft 365 に設定したプロフィール画像を削除したいという要望があったのですが、なかなか一筋縄ではいかなかったので備忘録としてメモしておきます。なお結論としては、現状としては GUI からは削除することはできず、PowerShell を使って削除する必要があります。
そもそもですが、Microsoft 365 でプロフィール画像を登録する場所は複数あります。
場所 | 画像の登録 | 画像の削除 |
Azure ポータル | できる | できる |
Microsoft 365 管理センター | できる | できない |
Delve | できる | できない |
Outlook | できる | できない |
Microsoft Teams | できる | できる ※ |
画像の登録はいずれの場所で行ってもそれぞれのサービスに反映されるようです。ですが、画像の削除に関しては、そもそもできなかったり、ほかのサービスへの反映がされなかったりします。Microsoft Teams の場合は、削除をすると、イニシャル画像(氏名が Takashi Shinohara であれば TS と表示される画像)が代わりに登録され、削除という動作にはなりません。ややこしいですね。
登録する場所はいろいろあるのですが、最終的に保存される場所は Azure Active Directory と Exchange の 2 つのようです。ほかにも SharePoint のユーザー プロファイルというのもあるのですが、現在どこで使われているのかを見つけることができませんでした。それぞれの画像は PowerShell で確認できます。
保存場所 | コマンドレット |
Azure Active Directory | Get-AzureADUserThumbnailPhoto |
Exchange | Get-UserPhoto |
Azure Active Directory の画像は Azure ポータルから GUI で削除することができますが、PowerShell では削除することはできないようです。逆に Exchange の画像は GUI から削除できず、Remove-UserPhoto コマンドレットを実行する必要があります。
ということで、現時点で Microsoft 365 からプロフィール画像を完全に削除するには以下の手順で行います。