2025-05-22 17:29:32 +09:00

236 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 実消化&アルトマーク Webアプリケーション
## 概要
実消化&アルトマークのWebアプリケーション。
以下の機能を提供する
- アルトマークデータ照会(施設・医師)
- 生物由来データ照会
- マスターメンテナンス
## 環境情報
- Python 3.9
- MySQL 8.x
- FastAPI
- PythonのWebアプリケーションフレームワーク
- VSCode
## 環境構築
- Pythonの構築
- Merck_NewDWH開発2021のWiki、[Python環境構築](https://nds-tyo.backlog.com/alias/wiki/1874930)を参照
- 「Pipenvの導入」までを行っておくこと
- 構築完了後、プロジェクト配下で以下のコマンドを実行し、Pythonの仮想環境を作成する
- `pipenv install --python <pyenvでインストールしたpythonバージョン> --dev`
- この手順で出力される仮想環境のパスは、後述するVSCodeの設定手順で使用するため、控えておく
- MySQLの環境構築
- Windowsの場合、以下のリンクからダウンロードする
- <https://dev.mysql.com/downloads/installer/>
- Dockerを利用する場合、「newsdwh-tools」リポジトリのMySQL設定を使用すると便利
- 「crm-table-to-ddl」フォルダ内で以下のコマンドを実行すると
- `docker-compose up -d`
- Dockerの構築手順は、[Dockerのセットアップ手順](https://nds-tyo.backlog.com/alias/wiki/1754332)を参照のこと
- データを投入する
- 立ち上げたデータベースに「src05」スキーマを作成する
- [ローカル開発用データ](https://ndstokyo.sharepoint.com/:f:/r/sites/merck-new-dwh-team/Shared%20Documents/03.NewDWH%E6%A7%8B%E7%AF%89%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA3/02.%E9%96%8B%E7%99%BA/90.%E9%96%8B%E7%99%BA%E5%85%B1%E6%9C%89/%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E9%96%8B%E7%99%BA%E7%94%A8%E3%83%87%E3%83%BC%E3%82%BF?csf=1&web=1&e=VVcRUs)をダウンロードし、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/login/maintlogin>」にアクセスし、ログイン画面が表示されていれば成功
## フォルダ構成
```text
.
├── 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.xxx``xxx`の部分が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でも可で、以下のコマンドを実行し、ハッシュ値を生成する
```bash
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 Hash Generator](https://www.srihash.org/)
### SRI ハッシュ値の設定方法
- 更新したスクリプトを読み込んでいる箇所の`integrity`属性値を、生成したハッシュ値に置き換える
- 以下は設定のサンプル
```bash
<script src="https://リンク/スクリプト.js" integrity="sha384-生成したハッシュ" crossorigin="anonymous"></script>
```