だ。ログ。

開発とかスノボとかやきうとか。

スクラッチのプラグインパッケージインストールの強みと弱み

特にEC-CUBE3ではそうだが、プラグインでの納品を視野に入れた開発を行う事も多い。
この場合、インストールしたモノが明示的に/app/Plugin/にインストールされるので、後々何をどうしたと言う事がわかりやすい。

ただ、これには大きな問題もある。
他で設定していたプラグインの周辺状況を確認していないと、そのプラグインを打ち消してしまう事がある。
これは発注時点でこちら側から命名規則なりを明示化させる事である程度は回避出来るとは思うが結局は外注して詳細に事を詰めずにやってしまうと

A:既存で動作していたプラグイン
B:今回納品したプラグイン

Bが干渉してしまいAのプラグインが正しく表示出来ない。と言うような問題が出て来る。
この辺の明確な指示もそうだが、結局は下準備が全てなんだなあ。としみじみと感じる。

そしてその修正が何故か元々作ったエンジニアの自分に来ている事で理不尽な気持ちに陥る月曜の午後。

DoctrineQueryBuilderのLimitを設定する

EC-CUBE3で利用されているDoctrine、QueryBuilderを使ったソースコードの簡素化ってのは慣れると便利だが
旧来のおっさんシステム屋からするとまだるっこしい。特にECサイト系の制作だと上限個数とかにこだわるクライアントさんが多い印象。

ってな訳で、QueryBuilderのオプションあんちょこ

$query = $this->createQueryBuilder('hogehoge')
# join系 (例はinner join)
->innerJoin('hoge.Hoge', 'hg')
# group by
->groupBy('fugafuga');
# order by
->orderBy("hogehoge",  "DESC")
# limit
->setMaxResults(10)

ざっくりとこの辺だけ分かれば後はなんとかなるかなと。
パラメータ系が揃っているが、自由度と言う意味でどうなのかと言う部分では使い倒していないのでなんとも言えない。

EC-CUBE3のパスワードリマインダの脆弱性のとりあえずの回避を行う

blog.tokumaru.org

徳丸浩先生が古い記事で上げていたパスワードリマインダがダメな理由。と言う記事を見てそう言えばEC-CUBEもリマインダ自体はメールアドレスを入力して、そのメールアドレスにリマインダメールを発射する仕組みになっている事に気付く。
総当り攻撃でメールアドレスを入力しまくってレスポンスの時間を推測すれば、ある場合と無い場合のレスポンス時間により、このメールアドレスはEC-CUBEのデータベース上に登録されている。と言う推測が出来てしまう。

1. 使わない

そのまんま。メールでのパスワードリマインダは使わない。
潔し。男気にあふれる選択。
ホントはこれに尽きる。パスワード忘れたらお問い合わせフォームからどうぞ。と。

2. 改修

んで本題。
徳丸先生の記事からすると、EC-CUBE3はセキュリティ的にいかんぞ。と。
本当だとパスワードの再設定は1回のみにしておくのが望ましい。またパスワードリマインダ使いました。と言う通知を何らかの方法で行う。と言う部分が必要になるかと思われる。

ただ、ここまでの要件を実装するとなると色々と改修が入る為、回避策と言う訳ではないが有効期間を持たせる形にしてみる。
/src/Eccube/Controller/ForgotController.php 90行目付近

            } else {
                log_warning('Un active customer try send reset password email: ', array('Enter email' => $form->get('login_email')->getData()));
            }
#ここにCookieで任意のデータを登録する
            setcookie("hogehoge", "fugafuga", PASSWORD_DEFAULT),time()+3600,"/forgot");
            return $app->redirect($app->url('forgot_complete'));

上記の場合、利用後1時間はパスワードリマインダを使いました。という記録を残す。と言うロジック。
ただCookie部分は適当に作っているが、本当であれば推測され辛いデータに形成しておくべき。
またリスクとしてはCookie削除すれば結局使えてしまう。またクローラースパイダー等のツールを使ってcookieを持たないツールの場合は無力。
そう考えると本当は実行した回数をカウントして保持して異常値を叩き出したら再発行を一旦停止する。と言う事も必要かもしれない。
これはモヤモヤと考えているだけだが、forgotコントローラが動いた段階で指定した時間のしきい値以上のリマインダが叩かれたらエラーページや申し訳ありませんが現在混雑中です。みたいな表示で逃げる。ってのもありかな。と。

んで、話しを戻してCookieを使った場合。
今度はこのCookieの値が存在した場合はindexコントローラのrenderに値を持たせて

<p><button type="submit" class="btn btn-primary btn-block">次のページへ</button></p>

を制御する。見せないとかボタンが押せないとかその辺でいいと思う。

ajaxのレスポンスヘッダを確認する

セキュリティ診断等で、自分のプログラムの妥当性を見るためにヘッダを確認する事が多々ある。
どうだっけ?ってなるので書いとく。

    success: function(data, return, ajxhead){
        var res_data = ajxhead.getAllResponseHeaders();
    }

コンソールからres_dataをウォッチすると中身が確認出来る。

LaravelでDB設定を入れても反映されない対処

環境構築をしていて、LaravelをインストールしてからDB設定を記述して

$results = DB::select('select * from test_table');

と、接続テストをすると

PDOException
SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES)

と表示されてしまいDBと疎通確認が取れない。
/config/database.phpには利用するDBの情報は入っているがユーザ名が homestead@localhost
となっている部分が問題。これはLaravel側が持っている.envファイルを優先して読みから出てしまっている。
サーバーから

$cd /Laravelがインストールされているディレクトリ/
$php artisan config:cache

キャッシュの再構築をしたら正しく接続出来た。
初期構築でコピペする。

Laravel5.4にて現在ルーティングされている一覧を確認する

大半は/routes/web.phpに記載されているがコマンドラインから

$ cd /laravelがインストールされているディレクトリ/
$ php artisan route:list

+--------+-----------+-------------------+---------+-------------------------------------------------+--------------+
| Domain | Method    | URI               | Name    | Action                                          | Middleware   |
+--------+-----------+-------------------+---------+-------------------------------------------------+--------------+
|        | GET|HEAD  | /                 |         | Closure                                         | web          |
|        | GET|HEAD  | api/user          |         | Closure                                         | api,auth:api |
|        | GET|HEAD  | hoge	         |         | Closure                                         | web          |
|        | GET|HEAD  | fuga	         | index   | App\Http\Controllers\FugaController@index       | web          |
|        | POST      | fuga	         | store   | App\Http\Controllers\FugaController@store       | web          |
|        | GET|HEAD  | fuga/create	 | create  | App\Http\Controllers\FugaController@create      | web          |
|        | GET|HEAD  | fuga/{}		 | show    | App\Http\Controllers\FugaController@show        | web          |
|        | PUT|PATCH | fuga/{}      	 | update  | App\Http\Controllers\FugaController@update      | web          |
|        | DELETE    | fuga/{}      	 | destroy | App\Http\Controllers\FugaController@destroy     | web          |
|        | GET|HEAD  | fuga/{}/edit 	 | edit    | App\Http\Controllers\FugaController@edit        | web          |
+--------+-----------+-------------------+---------+-------------------------------------------------+--------------+

こんな感じで返ってくる。

EC-CUBE3の値引き(某大手ペイメント対応)もする

前の記事 
rider-dice.hatenablog.com

でも触れた値引き、でもこれってEC-CUBE単体の値引きにしかなってなくって某大手のペイメント会社さんを通すと
購入金額のまま送られてしまっている。つまり自分の書いたコードだとコード足らずだったので調査。

今回調査したのは、EC-CUBE純正のクーポンプラグイン
これを使った場合、ペイメントに登録されるデータも値引きされた金額になっている。
と言う訳でソースコードを確認。

#346行目
$this->setCouponOrder($Order, $Coupon, $formCouponCd, $Customer, $discount, $app);

ここでオーダーの再受注をしている。
んで、setCouponOrderのロジックを見ると

        $total = $Order->getTotal() - $discount;
        $Order->setDiscount($Order->getDiscount() + $discount);
        $Order->setTotal($total);
        $Order->setPaymentTotal($total);
        $app['orm.em']->persist($Order);
        $app['orm.em']->flush($Order);

受注を更新する為にflushしているのと、setPaymentTotalに合計金額を入れている。
ここが抜けていた為に、DB上と表示上は金額が変更出来ているがペイメント会社さんには割引額が伝わっていなかった。
このままコピっとけば汎用性があるのでメモ。