SharePointで作られた社内ポータルをAngular+GraphAPIでステキに閲覧する②

[前回](https://qiita.com/teracy55/items/9b98ec09bf22c337abeb)に続いてAngular＋GraphAPIによる独自ポータルの構築を行っていきます。

前回は①、②について書きました。
今回は③～⑥まで一気に行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/69c53e36-88ad-cced-0051-a72d7b10ea7f.png)


# Graph API

Office365の様々なコンテンツにアクセスするための[GraphAPI](https://docs.microsoft.com/ja-jp/graph/?view=graph-rest-1.0)が用意されています。
その中から、必要なコンテンツに対するアクセス許可を設定する必要があります。

※[SharePoint API](https://docs.microsoft.com/ja-jp/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service)というREST APIも存在しますが、今回の手順で取得するアクセストークンでアクセスしてみたところ、`Invalid issuer or signature.`となってしまったのでGraphAPIを使うことにします。

## Azureでアクセス許可を追加

- 「アクセス許可の追加」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/2eda2285-aaa4-1597-74de-9f2d5115b0b5.png)

- 「Microsoft Graph」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/004f7917-ef0f-cc96-e981-a3a9a7ad23a0.png)

- 「委任されたアクセス許可」を選択
- Sitesで`Sites.ReadWrite.All`にチェックを入れて、「アクセス許可の追加」押下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/92b4bced-f58d-6372-bb42-17e110e9114c.png)


# APIコール

Angular側の組み込み方法を記載します。

## アクセストークンの取得

`acquireTokenSilent`で取得します。
※Silientを使用する場合、Azure側の認証で「暗黙の付与」でアクセストークンにチェックを入れておく必要があります。

```src/services/auth.service.ts
・・・
    /** アクセストークン */
    token: string;
・・・
    async aquireToken() {
        this.token = await this.msalService.acquireTokenSilent(environment.msal.scope);
    }
・・・
```

environments.tsにscopeを追加して、`Sites.ReadWrite.All`を入れておきます。

```environments.ts
export const environment = {
  production: false,
  msal: {
    clientID: '{{your client ID}}',
    authority: 'https://login.microsoftonline.com/{{your tenant ID}}',
    redirectUrl: 'http://localhost:4200/',
    scope: ['user.read', 'Sites.ReadWrite.All'],
  }
};
```

app.component.tsでログイン後にアクセストークン取得処理を追加する。

```src/app/app.component.ts
・・・
  async ngOnInit() {
    // ユーザー取得
    this.user = this.authService.getUser();
    if (this.user) {
      // ログイン済みの場合はアクセストークンを取得する
      await this.authService.aquireToken();
    }
  }
・・・
  /**
   * ログイン押下
   */
  async OnClickLogin() {
    // ログインポップアップ表示
    const token = await this.authService.showLoginPopup();
    if (token) {
      // アクセストークン取得
      await this.authService.aquireToken();
      // ユーザー情報を取得
      this.user = this.authService.getUser();
      // TOP画面に遷移
      this.router.navigate(['/pages']);
    } else {
      this.user = null;
      alert('ログイン失敗');
    }
  }
```

## APIにアクセス

### APIアクセス部分

httpリクエストのヘッダに`Authorization: Bearer {access token}`を指定するだけです

```src/sharepoint-api.service.ts
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';

/**
 * SharePointアクセス用API
 * 
 * Microsoft GraphAPIのエンドポイントに関しては以下を参照
 * https://docs.microsoft.com/ja-jp/graph/api/resources/sharepoint?view=graph-rest-1.0
 */
@Injectable({
    providedIn: 'root',
})
export class SharePointApiService {
    constructor(private http: HttpClient, private auth: AuthService) { }

    /**
     * SharePointのルートサイトを取得
     */
    async getRootSite() {
        const url = 'https://graph.microsoft.com/v1.0/sites/root';
        try {
            return await this.http.get(url, {
                headers: new HttpHeaders({ 'Authorization': 'Bearer ' + this.auth.token, })
            }).toPromise();
        } catch (err) {
            console.log(err);
            return null;
        }
    }
}
```
※SharePointの各種エンドポイントについては[こちら](https://docs.microsoft.com/ja-jp/graph/api/resources/sharepoint?view=graph-rest-1.0)を参照


### コンポーネント側

TOPページ表示時にSharePointのルートサイトを取得します。

```src/app/pages/top/top.component.ts
import { Component, OnInit } from '@angular/core';
import { SharePointApiService } from 'src/services/sharepoint-api.service';

@Component({
  selector: 'app-pages-top',
  template: `
  <h2>{{data.displayName}}</h2>
  <span>{{data.description}}</span>
  `,
})
export class TopComponent implements OnInit {
  /** SharePointサイト情報 */
  data: any;

  constructor(private spApi: SharePointApiService) {}

  ngOnInit () {
    this.getData();
  }

  /**
   * データ取得
   */
  async getData() {
    this.data = await this.spApi.getRootSite();
  }
}

```


# アクセス

ログインしなおすと無事にルートサイトのタイトルと説明が表示されます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/3357ec98-441c-0e5b-2177-63f749b4402d.png)



ちなみに以下のようなデータが返ってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/f70f0a82-574d-0b28-1d9b-e76412f1a4df.png)




# 最後に

これでSharePointに対してデータの読み書きをする準備ができました！！
あとは好きに画面を作って、データの読み書きをすれば完成です！




# 参考
[Microsoft GraphAPI](ttps://docs.microsoft.com/ja-jp/graph/?view=graph-rest-1.0)