• トップ
  • ブログ一覧
  • 【第3回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた【管理者ページ整備】
  • 【第3回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた【管理者ページ整備】

    広告メディア事業部広告メディア事業部
    2020.07.22

    IT技術

    ~第3回~モダンなフレームワークの使い方を学びながらブログシステムを構築

    連載「Python Responder + Firestore で、モダンかつサーバーレスなブログシステムを作ってみる」第3回目です。

    前回は、「Firebase のセットアップ」と「認証機能の基盤」を作成しました。

    featureImg2020.07.20【第2回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた【Firebase設定と認証機能実装】第2回~モダンなフレームワークの使い方を学びながらブログシステムを構築~本記事は、「Python Responder ...

    今回は、認証機能の整備ということで、「クッキー管理」と「ログアウト機能」を追加していきます。

    Cookie によるログイン管理

    第2回目で作成したログイン機能はちゃんと機能していますが、とても不便な部分があります。

    それは、「管理者ページに POST でしか入れない」ことです。

    本来ならば、一度ログインすれば、GET でアクセスしても、ログインを介さずにアクセスできます。

    そういった機能は、Cookie を使って構築していきましょう。

    Cookie を使って GET でも管理者ページに入れるように

    Responder では、Cookie の「セット」はresp.set_cookie() 、「取得」はreq.cookies です。

    したがって、以下の仕様にしたいと思います。

    1. ログイン成功時に Cookie をセット
    2. 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回へつづく!

    今回は、「認証機能の整備」と「管理者ページ整備」を行いました。

    まだあんまりブログっぽくないですね…。

    次回からは、いよいよ「ブログ記事とデータベース周りの整備」を行っていきます!

    具体的には、「カテゴリの追加」「記事の追加」などを実装していきます。

    お楽しみに!

    次回の記事はこちら

    featureImg2020.07.30【第4回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみる【モデルの構築】第4回~モダンなフレームワークの使い方を学びながらブログシステムを構築~連載「Python Responder + F...

    第1回はこちら

    featureImg2020.07.17【第1回】Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた【初期セットアップ編】モダンなフレームワークの使い方を学びながらブログシステムを構築今回より、また新たに Python WebAPI 関連の...

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

    広告メディア事業部

    広告メディア事業部

    おすすめ記事