2024-01-30 09:29:14 +09:00

16 KiB
Raw Permalink Blame History

実消化&アルトマーク Webアプリケーション

概要

実消化&アルトマークのWebアプリケーション。 以下の機能を提供する

  • アルトマークデータ照会(施設・医師)
  • 生物由来データ照会
  • マスターメンテナンス

環境情報

  • Python 3.9
  • MySQL 8.x
  • FastAPI
    • PythonのWebアプリケーションフレームワーク
  • VSCode

環境構築

  • Pythonの構築

    • Merck_NewDWH開発2021のWiki、Python環境構築を参照
      • 「Pipenvの導入」までを行っておくこと
    • 構築完了後、プロジェクト配下で以下のコマンドを実行し、Pythonの仮想環境を作成する
      • pipenv install --python <pyenvでインストールしたpythonバージョン> --dev
      • この手順で出力される仮想環境のパスは、後述するVSCodeの設定手順で使用するため、控えておく
  • MySQLの環境構築

    • Windowsの場合、以下のリンクからダウンロードする
    • Dockerを利用する場合、「newsdwh-tools」リポジトリのMySQL設定を使用すると便利
      • 「crm-table-to-ddl」フォルダ内で以下のコマンドを実行すると
    • データを投入する
      • 立ち上げたデータベースに「src05」スキーマを作成する
      • ローカル開発用データをダウンロードし、mysqlコマンドを使用して復元する
        • mysql -h <ホスト名> -P <ポート> -u <ユーザー名> -p src05 < src05_dump.sql
  • 環境変数の設定

    • 「.env.example」ファイルをコピーし、「.env」ファイルを作成する
    • 環境変数を設定する。設定内容はPRJメンバーより共有を受けてください
  • VSCodeの設定

    • 「.vscode/recommended_settings.json」ファイルをコピーし、「settings.json」ファイルを作成する
    • 「python.defaultInterpreterPath」を、Pythonの構築手順で作成した仮想環境のパスに変更する

実行

  • VSCode上で「F5」キーを押下すると、Webアプリケーションのサーバーが起動する
  • http://localhost:8000/maintlogin」にアクセスし、ログイン画面が表示されていれば成功

フォルダ構成

.
├── Dockerfile                          -- Dockerイメージを作成するためのファイル
├── Pipfile                             -- Pythonモジュールの依存関係を管理するファイル
├── Pipfile.lock                        -- Pythonモジュールの依存関係バージョン固定用ファイル
├── README.md                           -- 当ファイル
└── src                                 -- ソースコードの保管場所
    ├── aws                             -- AWSリソース操作用のコード
    │   ├── aws_api_client.py
    │   ├── cognito.py
    │   └── s3.py
    ├── controller                      -- ルーティング層。基本的に1画面1つ
    │   ├── bio.py
    │   ├── bio_download.py
    │   ├── login.py
    │   ├── logout.py
    │   └── menu.py
    ├── core                            -- APサーバーのコア設定。
    │   └── tasks.py                    -- 起動・終了時に実行するタスクを設定。
    ├── data                            -- 生物由来照会のエクセルファイルテンプレート。
    │   └── BioData_template.xlsx
    ├── db                              -- データベース関連処理。
    │   ├── database.py                 -- データベース接続、クエリ発行の共通モジュール。
    │   ├── sql_condition.py            -- SQLの条件式を組み立てるためのモジュール
    │   └── tasks.py                    -- coreに渡すタスク。サーバー起動時にDBとの接続モジュールの初期化、終了時にインスタンス破棄を行っている。
    ├── depends                         -- FastAPIの依存性注入(DI)使用するモジュールの置き場。Dependsで利用想定。
    │   ├── auth.py                     -- セッション等の認証関連
    │   ├── database.py                 -- リポジトリ層をコントローラーにDIするためのもの
    │   └── services.py                 -- サービス層をコントローラーにDIするためのもの
    ├── error                           -- エラー処理関連のモジュール置き場
    │   ├── exception_handler.py        -- FastAPI内部でエラー発生時のハンドリング
    │   └── exceptions.py               -- カスタム例外クラス
    ├── main.py                         -- APサーバーのエントリーポイント。ここでルーターやハンドラーの登録を行う
    ├── middleware                      -- ミドルウェアの設定
    │   └── middleware.py
    ├── model                           -- モデル層(MVCのM)
    │   ├── db                          -- リポジトリから返されるDBレコードのモデル
    │   │   ├── base_db_model.py
    │   │   ├── bio_sales_view.py
    │   │   ├── hdke_tbl.py
    │   │   ├── pharmacy_product_master.py
    │   │   ├── user_master.py
    │   │   └── wholesaler_master.py
    │   ├── jwt_token.py                -- 認証用JWTトークンのモデル
    │   ├── request                     -- 画面からのリクエストを受け付けるモデル
    │   │   ├── bio.py
    │   │   ├── bio_download.py
    │   │   └── login.py
    │   ├── session.py                  -- セッションデータのモデル
    │   └── view                        -- ビューモデル。画面に対応したモデル。
    │       ├── bio_disp_model.py
    │       ├── bio_view_model.py
    │       ├── logout_view_model.py
    │       ├── mainte_login_view_model.py
    │       ├── menu_view_model.py
    │       └── user_view_model.py
    ├── repositories                    -- リポジトリ層。DB操作モジュール置き場。
    │   ├── base_repository.py
    │   ├── bio_sales_view_repository.py
    │   ├── hdke_tbl_repository.py
    │   ├── pharmacy_product_master_repository.py
    │   ├── user_master_repository.py
    │   └── wholesaler_master_repository.py
    ├── router                          -- コントローラー層の共通ルーティングの定義
    │   └── session_router.py
    ├── services                        -- サービス層。ビジネスロジックはできる限りここに押し込む
    │   ├── base_service.py
    │   ├── batch_status_service.py
    │   ├── bio_view_service.py
    │   ├── login_service.py
    │   └── session_service.py
    ├── static                          -- 静的ファイルの配信ルートディレクトリ
    │   ├── css
    │   │   ├── bioStyle.css
    │   │   ├── datepicker.css
    │   │   ├── menuStyle.css
    │   │   └── pagenation.css
    │   ├── function
    │   │   └── businessLogicScript.js
    │   ├── img
    │   │   ├── icon_modal_confirm.png
    │   │   └── icon_modal_error.png
    │   ├── lib
    │   │   └── fixed_midashi.js
    │   ├── sample.css
    │   └── sample.js
    ├── system_var                      -- システム変数
    │   ├── constants.py                -- 定数
    │   └── environment.py              -- 環境変数
    ├── templates                       -- ビューテンプレートエンジンの格納場所(Jinja2)
    │   ├── _header.html                -- 共通ヘッダー
    │   ├── _modal.html                 -- モーダルの部品
    │   ├── bioSearchList.html
    │   ├── logout.html
    │   ├── maintlogin.html
    │   ├── menu.html
    └── util                            -- ユーティリティ関数置き場
        ├── sanitize.py                 -- モデルクラスのサニタイズを行うデコレータ
        └── string_util.py              -- 文字列操作関連のユーティリティ

(参考)ファイルの追いかけ方

  • APサーバーそのものは「src/main」にある。
    • ルーター、例外処理ハンドラ、開始終了タスクの設定、静的ファイルディレクトリのマウントを行っている
  • URLパスに対する操作の実装は、「controller」フォルダを見る
    • @router.xxxxxxの部分がHTTPメソッドに相当する。このデコレータが付与された関数が、HTTPメソッドを処理するパスオペレーション関数となる
    • パスオペレーション関数の引数には、リクエストで受け取るパラメータと、その関数内で使用できる依存関係を注入できる
      • Request型と、Response型の引数は、その名の通り。
      • str型, int型などの引数を指定した場合、その引数はクエリストリングを意味する
      • Dependsで初期値が設定される引数は、Depends関数に渡した関数が処理されてから代入される
        • たとえば、get_service関数にサービスクラスの型を渡すと、get_service関数でサービスクラスのインスタンスを作成して返してくれる
          • サービスクラスはリポジトリクラスに依存しているので、自分でインスタンスを組み立てる手間が省ける
      • formやリクエストボディのJSONを受け取る場合、リクエスト用のモデルクラスに「as_form」や「as_body」などの関数を実装し、リクエストを受け取れるようにする
      • ビジネスロジックは基本的にサービスクラスに押し込む。コントローラーではそのサービスクラスをDependsで依存して利用すること
  • ビジネスロジックに相当するサービスクラスは「services」フォルダに格納する。共通実装は以下。
    • REPOSITORIES定数に、依存するリポジトリクラスを辞書形式で指定する
    • CLIENTS定数に、依存するAWS APIクライアントクラスを辞書形式で指定する
    • __init__コンストラクタ内で、2つの定数に指定したキーに紐付いたインスタンスが渡ってくるため、インスタンス変数として登録する
    • あとは、ビジネスロジックにあたる関数を生やしていく
  • DBへのアクセスを行うリポジトリクラスは「repositories」フォルダに格納する。
    • SQL文を用意し、_dbインスタンス変数のメソッドを利用してクエリを実行する。
    • 必要に応じて条件設定をする。条件設定にはSQLConditionクラスを使用する。
      • BioSalesViewRepositoryのやり方が参考になる
    • リポジトリクラスは、サービスクラスで利用するようにする(そのために、サービスクラス側に依存関係を書いている)
  • モデルクラスは、「models」フォルダに格納する
    • HTTPリクエスト用のモデルクラスは「request」フォルダへ
    • ビュー表示用のモデルクラス(View Model)は「view」フォルダへ
      • 画面への項目埋め込みや、非表示の制御を行うため、View Modelに値を詰めて、テンプレート側で操作するようにする
    • DBから取得したレコードのモデルクラスは「db」フォルダへ
    • 内部処理に利用するモデルクラスは「internal」フォルダへ
  • 「static」フォルダは、静的ファイルの置き場所
    • CSS, JS、画像ファイルを置く。
    • 画面の細かな制御は「BusinessLogicScript.js」で行っている。現行からちょこちょこ変える必要がある。
    • CSSも、現行は画面ごとに分かれているが、一つのベーススタイルにまとめたい
  • 「templates」フォルダは、テンプレートエンジンを格納する
    • 各画面1つのテンプレートエンジンを用意する
      • 内部で使う変数は、コントローラーで「templates.TemplateResponse」」に詰めて渡す
      • テンプレート内でincludeする用途のテンプレートは先頭に「_」をつける
        • _header.htmlは、<head>タグ内に記載する部品。共通的に読み込むCSS等のファイルを指定する。
      • PHPでは分岐などをベタ書きしているが、View Modelに宣言的な関数を用意して、可読性を向上させている。
  • コントローラーの共通処理は、「router」フォルダ内のモジュールで実装している
    • コントローラーのrouter変数が、router.route_class = AfterSetCookieSessionRouteとなっている場合、レスポンス時、クッキーにセッションキーを登録する動きをする
    • コントローラーのrouter変数が、router.route_class = Authenticateとなっている場合、以下の動きをする
      • リクエスト到達時にセッションの有無をチェックする
      • レスポンス時、クッキーにセッションキーを登録する

HTMLで読み込んでいるスクリプトのSRIハッシュ値を生成・設定する方法

サブリソース完全性 (Subresource Integrity, SRI) とは

CDN などから取得したリソースが意図せず改ざんされていないかをブラウザーが検証するセキュリティ機能です。 SRI を利用する際には、取得したリソースのハッシュ値と一致すべきハッシュ値を指定します。

詳細:https://developer.mozilla.org/ja/docs/Web/Security/Subresource_Integrity

実消化&アルトマークのWebアプリケーションでは、複数の外部スクリプトを読み込んで動作しているため、読み込むスクリプトを変更した場合は、 タグの属性値integrityに設定されているスクリプトのハッシュ値を更新する必要がある。

SRI ハッシュ値の生成方法(サーバー内のスクリプトについて)

  • サーバー内に保管されているスクリプトを更新した場合、Linux環境WSL2でも可で、以下のコマンドを実行し、ハッシュ値を生成する
cat <更新したスクリプトファイル名> | openssl dgst -sha384 -binary | openssl base64 -A

参考:https://developer.mozilla.org/ja/docs/Web/Security/Subresource_Integrity#sri_%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%83%84%E3%83%BC%E3%83%AB

SRI ハッシュ値の生成方法(外部サイトから読み込んでいるスクリプトについて)

  • 外部サイトから読み込んでいるスクリプトを更新した場合、下記のMDNオンラインツールでハッシュ値を生成する

SRI ハッシュ値の設定方法

  • 更新したスクリプトを読み込んでいる箇所のintegrity属性値を、生成したハッシュ値に置き換える
  • 以下は設定のサンプル
<script src="https://リンク/スクリプト.js" integrity="sha384-生成したハッシュ" crossorigin="anonymous"></script>