【第3回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた【管理者ページ整備】
2021.12.20
~第3回~モダンなフレームワークの使い方を学びながらブログシステムを構築
連載「Python Responder + Firestore で、モダンかつサーバーレスなブログシステムを作ってみる」第3回目です。
前回は、「Firebase のセットアップ」と「認証機能の基盤」を作成しました。
今回は、認証機能の整備ということで、「クッキー管理」と「ログアウト機能」を追加していきます。
Cookie によるログイン管理
第2回目で作成したログイン機能はちゃんと機能していますが、とても不便な部分があります。
それは、「管理者ページに POST でしか入れない」ことです。
本来ならば、一度ログインすれば、GET でアクセスしても、ログインを介さずにアクセスできます。
そういった機能は、Cookie を使って構築していきましょう。
Cookie を使って GET でも管理者ページに入れるように
Responder では、Cookie の「セット」は resp.set_cookie() 、「取得」は req.cookies です。
したがって、以下の仕様にしたいと思います。
- ログイン成功時に Cookie をセット
- GET でのアクセス時に、Cookie にログインユーザがいれば、管理者ページを表示
コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # contorollers.py内 COOKIE_EXPIRES = 5 # days later @api.route('/admin') class Admin: async def on_get(self, req, resp): # [new] ログインしてなければ if req.cookies.get('session') is None: api.redirect(resp, '/login') # [new] ログイン済み else: resp.html = api.template('admin.html', title='管理者ページ', token=req.cookies.get('token'), name=req.cookies.get('username')) async def on_post(self, req, resp): # POSTデータを取得 data = await req.media() email = data['email'] password = data['password'] # 認証 res = _login(email, password) if 'error' not in res: # [new] クッキーにログイン情報をセット expires = datetime.now() + timedelta(COOKIE_EXPIRES) resp.set_cookie(key='session', value=session, expires=expires) resp.set_cookie(key='username', value=res['displayName'], expires=expires) resp.set_cookie(key='email', value=email, expires=expires) # 認証成功ならば管理者ページへ resp.html = api.template('admin.html', title='管理者ページ', name=res['displayName']) else: # 認証失敗ならばエラーメッセージをログイン画面に渡してリダイレクト api.redirect(resp, '/login?error={}'.format(res['error']['errors'][0]['message'])) |
これで、ログインをしていれば、管理者ページに GET でログインできます。
Cookie の破棄
「一定時間後に Cookie の自動破棄をする」仕様にしたい場合は、どうすればいいのでしょう?
そんな時は、 expires=**, max_age=** で変更します。
expires は「日付」、 max-age は「破棄までの秒数」を指定します。
今回は、5日間としました。
ログアウト機能
次に、ログアウト機能を「/logout」に作成します。
実装内容はとても単純で、Cookie を破棄すれば OK です。
1 2 3 4 5 6 7 8 9 | # controllers.py内 @api.route('/logout') def logout(req, resp): # クッキーのログイン情報を破棄してリダイレクト resp.set_cookie(key='session', value='', expires=0, max_age=0) resp.set_cookie(key='username', value='', expires=0, max_age=0) resp.set_cookie(key='email', value='', expires=0, max_age=0) api.redirect(resp, '/login') |
実際に、ログイン後に「/logout」にアクセスしてみてください。
その後「/admin」にGETでアクセスしても、ログイン画面に戻されるはずです。
管理者ページを整える
最後に、管理者ページを軽く整えておきましょう。
管理者ページでは、「投稿の編集や追加」「プロフィールの編集」などができます。
注意
あなたの好みのデザインを使って構いません。
また、今回作ったデザインに仮データは入っていますが、これはいずれ消します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <!-- templates/admin.html 管理者ページ --> {% extends "layout.html" %} {% block content %} <br> <h1>My Blog Name | 管理者ページ</h1> <p>こんにちは,{{ name }} さん</p> <div class="main-container"> <div class="admin-main-menu"> <h2>投稿一覧</h2> <table> <tr> <th style="width: 5%;">#</th> <th style="width: 40%;">タイトル</th> <th style="width: 10%;">作成者</th> <th style="width: 10%;">スラッグ</th> <th style="width: 10%;">カテゴリ</th> <th style="width: 10%;">タグ</th> <th style="width: 15%;">最終更新日</th> </tr> <tr> <td>0</td> <td>テスト投稿</td> <td>rightcode</td> <td>test-post</td> <td>Test</td> <td>post</td> <td>2020.06.03</td> </tr> <tr> <td>1</td> <td>ブログを作りました!</td> <td>rightcode</td> <td>create-blog</td> <td>未分類</td> <td></td> <td>2020.06.03</td> </tr> </table> </div> <div class="admin-side-menu"> <h2>Menu</h2> <ul> <li><a href="/admin/profile">プロフィール確認・編集</a></li> <li><a href="/admin/new">新規追加</a></li> <li><a href="/admin">投稿一覧</a></li> <li><a href="/logout">ログアウト</a></li> </ul> </div> </div> {% endblock %} |
CSS 追記
さらに、CSSも追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | .main-container{ display: flex; } .admin-main-menu{ width: 80%; } .admin-main-menu table{ width: 95%; border-collapse:collapse; margin:auto; } .admin-main-menu td,th{ padding:10px; } .admin-main-menu th{ color:#fff; background: #657ccb; border-right: 1px solid #416092; } .admin-main-menu td{ text-align: center; border-bottom:1px solid #c8d6ee; } .admin-side-menu{ width: 20%; } .admin-side-menu a{ text-decoration: none; color: #1e366a; } .admin-side-menu a:hover{ opacity: 0.7; } .admin-side-menu h2{ color: #1e366a; margin-top: 1.5em; margin-bottom: 0; } .admin-side-menu ul{ color: #1e366a; border-top: solid #1e366a 1px; border-bottom: solid #1e366a 1px; padding: 2.5em 0 0.5em 1.5em; margin-top: 0.5em; } .admin-side-menu ul, li{ line-height: 1.5; padding: 0.5em 1.5em; } |
完成!
サイドメニューのリンクは、後ほどコーディングしていきます。
もちろん、今はまだ動作しません。
第4回へつづく!
今回は、「認証機能の整備」と「管理者ページ整備」を行いました。
まだあんまりブログっぽくないですね…。
次回からは、いよいよ「ブログ記事とデータベース周りの整備」を行っていきます!
具体的には、「カテゴリの追加」「記事の追加」などを実装していきます。
お楽しみに!
次回の記事はこちら
第1回はこちら
こちらの記事もオススメ!
書いた人はこんな人
- 「好きを仕事にするエンジニア集団」の(株)ライトコードです!
ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。
システム開発依頼・お見積もり大歓迎!
また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。
以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit
- ライトコードの日常2月 29, 2024座談会はじめました!ライトコードの話ちょっと聞いてみませんか?
- ライトコードの日常12月 27, 2023年忘れ!ライトコード大忘年会2023
- ライトコードの日常12月 1, 2023ライトコードクエスト〜東京オフィス歴史編〜
- ITエンタメ10月 13, 2023Netflixの成功はレコメンドエンジン?