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