firebaseでユーザ認証して人の顔年齢を試して遊ぶものをFreenom,Netlifyで公開までやる

### 概要
Vue.jsで作ったサイトをFirebaseにユーザー認証をお願いして、ログインしないと入れないページにして、人の顔年齢（Computer Vision API）で遊んで、freenomとNetlifyで独自ドメインで公開する
### できたもの
![スクリーンショット 2020-05-28 1.01.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/d71070d2-4bef-082f-730b-f1541d6f546d.png)
写真を入れると年齢をかえしてくれます。
### 環境
```
macOS Catalina 
Visual Studio Code 1.45.1
Node.js: v13.11.0
npm:6.14.5
Vue:@vue/cli 4.3.1

```
### 大まかな流れ
Vue.jsとFirebaseでユーザー認証ありのプロジェクトをつくる
　　　↓
Computer Vision APIをつかって顔認識のぺーじをつくる
　　　↓
freenomでドメインを取る
　　　↓
Netlifyに freenomドメインをあててDeploy

メインの構成はこんな感じです

```
App.vue
main.js
assets
components
　- Signup.vue
　- HelloWorld.vue
　- Signin.vue
router
　- index.js

```

### Vue.jsとFirebaseでユーザー認証ありのプロジェクトをつくる
こちらがめちゃくちゃわかりやすかったです。
こちらを参考にVue.jsとFirebaseでユーザー認証ありのプロジェクトをつくる

[Vue\.js \+ Firebase を使って爆速でユーザ認証を実装する \- Qiita](https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241)

```vuejs:src/components/Signin.vue
<template>
  <div class="signin">
    <h2>Sign in</h2>
    <b-container class="bv-example-row">
    <b-row class="justify-content-md-center">
    <b-form inline>
    <b-input
      id="inline-form-input-name"
       v-model="username"
      class="mb-2 mr-sm-2 mb-sm-0"
      placeholder="Username"
    ></b-input>
    <b-input type="password" id="text-password" v-model="password" aria-describedby="Password" placeholder="Password"></b-input>
    <!-- <button @click="signIn">Signin</button> -->
    <b-button variant="outline-primary" @click="signIn">Signin</b-button>
    </b-form>
    </b-row>
    <b-row>
    <b-col><p>You don't have an account?
      <router-link to="/signup">create account now!!</router-link>
    </p>
    </b-col>
    </b-row>
    </b-container>
  </div>
</template>

<script>
import firebase from 'firebase'

export default {
  name: 'Signin',
  data: function () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    signIn: function () {
      firebase.auth().signInWithEmailAndPassword(this.username, this.password).then(
        user => {
          // alert('Success!')
          this.$router.push('/')
        },
        err => {
          alert(err.message)
        }
      )
    }
  }
}
</script>
<style>
.signin {
  line-height:5;
}
.signin h2{
  margin:2rem auto;
}
button.btn.btn-outline-primary {
    margin: 0 1rem;
}
</style>

```
```vuejs:src/components/Signup.vue

<template>
  <div class="signup">
    <h2>Sign up</h2>
    <input type="text" placeholder="Username" v-model="username">
    <input type="password" placeholder="Password" v-model="password">
    <button @click="signUp">Register</button>
    <p>Do you have an account?
      <router-link to="/signin">sign in now!!</router-link>
    </p>
  </div>
</template>

<script>
import firebase from 'firebase'

export default {
  name: 'Signup',
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    signUp: function () {
      firebase.auth().createUserWithEmailAndPassword(this.username, this.password)
        .then(user => {
          alert('Create account: ', user.email)
        })
        .catch(error => {
          alert(error.message)
        })
    }
  }
}
</script>

```
### Computer Vision APIをつかって顔認識のぺーじをつくる
こちらを参考に顔認識のページをつくる
[Azure画像認識系の機能をいくつか試してみた（Face API / Custom Vision API / Computer Vision API） \- Qiita](https://qiita.com/shima-07/items/d247384c084c55b8fe04)

```vuejs:src/components/HelloWorld.vue

<template>
  <div class="hello">
    <p class="lh5">{{ msg }}</p>
    <div id="appFaceAPI-File">

      <div class="row">
        <div class="col">
            <h1>その写真の人が何歳に見えるかおしえてあげよう</h1>
        </div>
      </div>

      <div class="row">
        <div class="col">
          <div class="form-group">
            <!-- https://bootstrap-vue.org/docs/components/form-file -->
            <div>
              <!-- Styled -->
              <b-form-file
                v-model="file"
                :state="Boolean(file)"
                placeholder="Choose a file or drop it here..."
                drop-placeholder="Drop file here..."
                @change="handlerFileChange"
              ></b-form-file>
              <div class="mt-3">Selected file: {{ file ? file.name : '' }}</div>
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col">
          <pre><code>{{ response }}</code></pre>
        </div>
      </div>

    </div>
    <div class="siout">
    <b-button variant="secondary" @click="signOut">Sign out</b-button>
    </div>
  </div>
</template>
<script>
import firebase from 'firebase'
import axios from 'axios'

export default {
  name: 'HelloWorld',
  data: function () {
    return {
      response: '',
      fill: null,
      msg: '良い写真ある？',
      name: firebase.auth().currentUser.email
    }
  },

  methods: {
    signOut: function () {
      firebase.auth().signOut().then(() => {
        this.$router.push('/signin')
      })
    },
    handlerFileChange: async function (e) {
      console.log('handlerFileChange')
      const files = e.target.files || e.dataTransfer.files
      const file = files[0]
      let contentBuffer = await this.readFileAsync(file)
      // console.log(contentBuffer);
      this.sendCognitiveAsFile(contentBuffer)
    },
    readFileAsync: function (file) {
      return new Promise((resolve, reject) => {
        let reader = new FileReader()
        reader.onload = () => {
          resolve(reader.result)
        }
        reader.onerror = reject
        reader.readAsArrayBuffer(file)
      })
    },
    sendCognitiveAsFile: async function (contentBuffer) {
      // const FACE_API_ENDPOINT_URL = '***'
      const qs = require('querystring')
      const params = qs.stringify({
        'returnFaceId': 'true',
        'returnFaceLandmarks': 'false',
        'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' + 'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
      })
      const FACE_API_ENDPOINT_URL = `{取得したエンドポイント}/face/v1.0/detect?${params}`

      const config = {
        url: FACE_API_ENDPOINT_URL,
        method: 'post',
        headers: {
          'Content-type': 'application/octet-stream',
          'Ocp-Apim-Subscription-Key': '***'
        },
        data: contentBuffer
      }

      // axios
      try {
        // POSTリクエストで送る
        const responseAzure = await axios.request(config)
        console.log('post OK')
        // データ送信が成功するとレスポンスが来る
        console.log(responseAzure.data)
        // ageを取得
        const lookage = responseAzure.data[0].faceAttributes.age
        this.response = `${lookage} 歳にみえるね`
      } catch (error) {
        console.error(error)
      }
    }
  }
}
</script>
<style >
.col h1{
  font-size:100%;
}
div.form-group {
    max-width: 380px;
    margin: auto;
    width: 80%;
}
.lh5 {
    line-height: 5;
  }
.siout {
    text-align: right;
    padding: 1rem;
    position: fixed;
    top: 1vh;
    right: 3rem;
}
#app{
  position:relative;
}
  </style>


```

### freenomでドメインを取る
こちらを参考にまずは好きなドメインを取得
[爆速！Vercelとfreenomで独自ドメインのサイトを無料で作成する \- Qiita](https://qiita.com/n0bisuke/items/901154531ea14f978bd4#freenom%E3%81%A8vercel%E3%81%A7%E7%8B%AC%E8%87%AA%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AAweb%E3%82%B5%E3%82%A4%E3%83%88)

### NetlifyにDeploy
GitHubのリポジトリを作成して、作成したプロジェクトをPushしましょう。
[Netlify](https://www.netlify.com/)のページへ行き、[Get started in seconds]ボタンを押して![スクリーンショット 2020-05-27 23.22.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/19c26b30-922e-2fd6-c5b9-48409b898a18.png)
GitHubと連携しましょう
![スクリーンショット 2020-05-27 23.21.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/225d9c03-730c-e49d-2aad-0ae4140111db.png)
Netlify の管理画面に入れたら、右上にある「New site from Git」を選択します。
![スクリーンショット 2020-05-27 23.27.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/db28b476-be26-68f6-85e3-8f010d35d370.png)
GitHubを選びます
先ほど作ったリポジトリを選んでDeploy settingsを埋めていきます
![スクリーンショット 2020-05-27 23.30.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/8da40071-90a5-5add-4a9f-ceb6af5d6f88.png)
Deploy siteボタンを押せば完了！

＊ここでエラーになった人！（わたし！）
Gitの作り方によってはPublish先がdistだけでは展開できず、エラーにあることがあります。
Gitの置いてある位置からみているようなので、
works/fbaseApp/distとかになる場合もあります。

Deployが進んだら、ご丁寧に次の手順が出ています
![スクリーンショット 2020-05-27 23.31.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/a7756cb4-c465-9d05-301e-699ba5233277.png)
２を押しましょう
![スクリーンショット 2020-05-27 23.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/2339bb13-f8bb-51e6-96a4-79de0629a904.png)
ここに、freenomで作ったドメインを入れます
とりあえずエラーっぽい感じですが気にせずここを押すと
![スクリーンショット 2020-05-27 23.56.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/61603822-cbab-4e16-b746-8e26aef9be14.png)

```
Alternative: point A record to 1**.**.*.**
```
こういったものが書かれているのでこの番号をだしたまま
つぎにfreenomの管理画面からManage Freenom DNSにいきます
![スクリーンショット 2020-05-27 23.50.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/ed4d78b3-59b6-a4ef-f0b2-9e9e87d18be6.png)
ここに先ほどのNetlifyから取得した番号を入れる
![スクリーンショット 2020-05-28 0.31.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/f00a9f80-621c-143a-a3cb-64b038132188.png)

またNetlifyにもどって、さっきの画面の「Check DNS configuration」をおす)(さっきとちがうモーダルが出ます)
![スクリーンショット 2020-06-03 10.07.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/549b7b75-eadc-d42d-bf37-eb9506c7fb93.png)
この４つのDNSをfreenomにもどって
![スクリーンショット 2020-08-18 10.49.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282291/ac77c889-367e-9e8e-ced3-bf6fc833ac53.png)

1.Manage Freenom DNS
2.Use custom nameservers (enter below) にCheckを変える
3.NetlifyのNameserverを４ついれていく

せっかくなのでHttpsにしないと！
Netlifyにもどりましょう。
Setting　＞　HTTPS
SSL/TLS certificate
この下の
enebled 
Verify Provide your own certificate
二つボタンがあるので左のVerify をおすだけです！

これでしばらく待てばfreenomでとったドメインにへんこうされてHTTPSになっている!


### きになるところ
こんなに表示は遅いものなのだろうか・・・
リダイレクトがうまくいっていないような・・・