//tips
//smart contract
認証設定の続きを行う。
Pagesのfireフォルダのindex.jsを書き換える。http://localhost:3000/fireにアクセスするとgoogleアカウントのログインウィンドウがポップアップして現れ、そちらでログインするとアカウント情報がページに反映される。
ポップアップを禁止しているブラウザは表示されないので設定変更する必要あり。
関数コンポーネントに入る前にauthと認証プロバイダの準備。
const auth = firebase.auth()
const provider = new firebase.auth.GoogleAuthProvider();
これらを利用して認証を行う。ログイン処理は関数コンポーネント内に副作用フックを使って用意する。
export default function Home() {
const [message, setMessage] = useState('wait...')
useEffect(() => {
auth.signInWithPopup(provider).then(result=> {
setMessage('logined: ' + result.user.displayName)
})
}, [])
signInWithPopup(provider)を呼び出してログインウィンドウによるログイン処理を実行。thenのアロー関数で result.user.displayNameの値をsetMessageで表示。ログインユーザー名が現れる。
return (
<div>
<Layout header="Next.js" title="Top page.">
<div className="alert alert-primary text-center">
<h5 className="mb-4">{message}</h5>
ログイン情報を以下のような形で用意。auth.currentUserがnullでなくログインしていれば、uid,displayname,email,phonenumberを表示。
<p className="h6 text-left">
uid: {auth.currentUser != null ? auth.currentUser.uid : ''}<br/>
displayName: {auth.currentUser != null ? auth.currentUser.displayName : ''}<br/>
email: {auth.currentUser != null ? auth.currentUser.email : ''}<br/>
phoneNumber: {auth.currentUser != null ? auth.currentUser.phoneNumber : ''}
</p>
</div>
</Layout>
</div>
)
}
認証が設定できたのでfirestoreのルールをログインしている時だけアクセスできるように変更する。if request.auth != null;とすれば認証されている場合のみアクセス可能となる。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
同時にfireフォルダのindex.jsも修正。
ログインしている時だけデータ表示させるように変更した。thenの後にcatchを加えて、ログインに失敗した際に発生する例外処理を行っている。ログインしなかった場合にはnot loginedをセットさせている。
useEffect(() => {
auth.signInWithPopup(provider).then(result=> {
setMessage('logined: ' + result.user.displayName)
}).catch((error) => {
setMessage('not logined.')
})
またログアウトはauth.signOut() を実行すれば良いだけなので非常にシンプル。
メッセージ機能付きアドレスブックを作成していく。
/address:トップページ、登録してあるデータのリスト、登録ページへの移動ボタンを用意する
/address/add:データの登録ページ
/address/info:選択したデータの詳細表示ページ。データ内容の他、メッセージ送信のフォーム、送信メッセージのリストが表示される。
Addressフォルダを作成し、index.jsファイルをその中に生成。
// アドレスデータの取得と表示
useEffect(() => {
if (auth.currentUser != null) {
setUser(auth.currentUser.displayName)
setMessage(auth.currentUser.displayName + 'さんの登録アドレス')
db.collection('address')
.doc(auth.currentUser.email)
.collection('address').get()
Addressというコレクションからログインしているアカウントのemailのドキュメントを取得している。ここで各アカウントのメールアドレスをキーにしてデータがまとめられていることがわかる。
さらに取り出したドキュメントから更にaddressというコレクションを取り出している。これがログインしているアカウントのアドレスデータとなる。
データ構造としてaddressコレクション内に各アカウントのドキュメントを用意し、その中のaddressコレクションにアドレスブックのデータを追加する形にしている。
また、next.jsはアドレスが変わって別のページにジャンプしてもページ自体をロードするのではなくコンポーネントを切り替えているだけのためコンポーネント外にあるauth.signOut()は別のaddress下位ページからrouter.pushで移った際には問題ない。
.then((snapshot)=> {
snapshot.forEach((document)=> {
const doc = document.data()
addresses.push(
<li className="list-group-item list-group-item-action p-1"
onClick={doLink} id={document.id}>
{doc.flag ? '√' : ''}{doc.name} ({doc.mail})
</li>
)
})
setData(addresses)
})
} else {
addresses.push(
<li key="1">can't get data.</li>
)
}
}, [message])
Add.jsページも見ていく。ここではフォームにテキストを入力し、その内容をfirestorageに保存。
アドレスデータはforestoreの「address」コレクションにある自身のメールアドレスのブック内に更にaddressというコレクションを用意して保管している。
ここでは、doactionの中で、ボタンをクリックするとフォームの内容をfirestorageに保管している。
collection().add()にしてしまうと保管ドキュメントにランダムなIDが設定されてしまうので、addressコレクションの中に登録情報のメールアドレスをキーに指定して、ドキュメントを作成。docでキーを指定し、setでそのデータを設定する。setはドキュメントの内容を更新するのに使うメソッド。
export default function Add() {
…
// アドレスの登録
const doAction = ((e)=> {
…
db.collection('address').doc(auth.currentUser.email)
.collection('address').doc(mail).set(ob).then(ref=> {
router.push('/address')
})
})