From 35720c70db310ed91437b7067e5b16f247efa37d Mon Sep 17 00:00:00 2001 From: sakaguchi Date: Wed, 3 Jun 2026 21:59:41 +0900 Subject: [PATCH] =?UTF-8?q?fix=20#3390=20=E3=80=90=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=83=95=E3=82=A9=E3=83=BC=E3=83=A0=E3=80=91=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89?= =?UTF-8?q?=E3=81=AE=E6=95=B0=E3=81=8C=E5=A4=9A=E3=81=84=E5=A0=B4=E5=90=88?= =?UTF-8?q?=E3=81=AB=E3=80=81=E5=8F=97=E4=BF=A1=E3=83=87=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E7=94=A8=E3=83=86=E3=83=BC=E3=83=96=E3=83=AB=E3=81=AE=E3=83=95?= =?UTF-8?q?=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89=E3=81=8C=E4=B8=8D=E8=B6=B3?= =?UTF-8?q?=E7=8A=B6=E6=85=8B=E3=81=A7=E4=BD=9C=E6=88=90=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E3=81=8B=E3=81=A9=E3=81=86=E3=81=8B=E7=A2=BA=E8=AA=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TwoFactorAuthenticationsService.php | 9 ++- .../TwoFactorAuthenticationsServiceTest.php | 13 +++- .../src/Service/MailMessagesService.php | 29 +++++-- .../Service/MailMessagesServiceTest.php | 75 ++++++++++++++++--- 4 files changed, 106 insertions(+), 20 deletions(-) diff --git a/plugins/baser-core/src/Service/TwoFactorAuthenticationsService.php b/plugins/baser-core/src/Service/TwoFactorAuthenticationsService.php index 8bb5f62d65..7e1e7c7774 100644 --- a/plugins/baser-core/src/Service/TwoFactorAuthenticationsService.php +++ b/plugins/baser-core/src/Service/TwoFactorAuthenticationsService.php @@ -14,6 +14,7 @@ use BaserCore\Mailer\TwoFactorAuthenticationMailer; use BaserCore\Model\Table\TwoFactorAuthenticationsTable; use Cake\Core\Configure; +use Cake\I18n\FrozenTime; use Cake\Mailer\MailerAwareTrait; use Cake\ORM\TableRegistry; @@ -81,12 +82,16 @@ public function verify(int $userId, string $code): bool return false; } - $expire = time() - (Configure::read('BcApp.twoFactorAuthenticationCodeAllowTime') * 60); + $allowTime = (int)Configure::read('BcApp.twoFactorAuthenticationCodeAllowTime', 10); + if ($allowTime < 1) { + $allowTime = 10; + } + $expire = FrozenTime::now()->subMinutes($allowTime); $twoFactorAuthentication = $this->TwoFactorAuthentications->find() ->where(['user_id' => $userId]) ->where(['code' => $code]) ->where(['is_verified' => 0]) - ->where(['modified >=' => date('Y-m-d H:i:s', $expire)]) + ->where(['modified >=' => $expire]) ->first(); if (!$twoFactorAuthentication) { return false; diff --git a/plugins/baser-core/tests/TestCase/Service/TwoFactorAuthenticationsServiceTest.php b/plugins/baser-core/tests/TestCase/Service/TwoFactorAuthenticationsServiceTest.php index fe9e54bc06..754a8cb4c2 100644 --- a/plugins/baser-core/tests/TestCase/Service/TwoFactorAuthenticationsServiceTest.php +++ b/plugins/baser-core/tests/TestCase/Service/TwoFactorAuthenticationsServiceTest.php @@ -14,6 +14,7 @@ use BaserCore\Service\SiteConfigsServiceInterface; use BaserCore\Service\TwoFactorAuthenticationsService; use BaserCore\TestSuite\BcTestCase; +use Cake\Core\Configure; use Cake\ORM\TableRegistry; use Cake\TestSuite\EmailTrait; use CakephpFixtureFactories\Scenario\ScenarioAwareTrait; @@ -39,6 +40,11 @@ class TwoFactorAuthenticationsServiceTest extends BcTestCase */ public $TwoFactorAuthentications; + /** + * @var mixed + */ + private $originalAllowTime; + /** * Set Up * @@ -47,6 +53,8 @@ class TwoFactorAuthenticationsServiceTest extends BcTestCase public function setUp(): void { parent::setUp(); + $this->originalAllowTime = Configure::read('BcApp.twoFactorAuthenticationCodeAllowTime'); + Configure::write('BcApp.twoFactorAuthenticationCodeAllowTime', 10); $this->TwoFactorAuthenticationsService = new TwoFactorAuthenticationsService(); $this->TwoFactorAuthentications = TableRegistry::getTableLocator()->get('BaserCore.TwoFactorAuthentications'); } @@ -58,6 +66,8 @@ public function setUp(): void */ public function tearDown(): void { + Configure::write('BcApp.twoFactorAuthenticationCodeAllowTime', $this->originalAllowTime); + unset($this->originalAllowTime); unset($this->TwoFactorAuthenticationsService); unset($this->TwoFactorAuthentications); parent::tearDown(); @@ -123,7 +133,8 @@ public function testSend() */ public function testVerify($expected, $saveData, $verifyData) { - $this->TwoFactorAuthentications->save($this->TwoFactorAuthentications->newEntity($saveData)); + $twoFactorAuthentication = $this->TwoFactorAuthentications->newEntity($saveData); + $this->assertNotFalse($this->TwoFactorAuthentications->save($twoFactorAuthentication)); $result = $this->TwoFactorAuthenticationsService->verify($verifyData['user_id'], $verifyData['code']); $this->assertEquals($expected, $result); } diff --git a/plugins/bc-mail/src/Service/MailMessagesService.php b/plugins/bc-mail/src/Service/MailMessagesService.php index e55dd7887b..c1a75e016a 100644 --- a/plugins/bc-mail/src/Service/MailMessagesService.php +++ b/plugins/bc-mail/src/Service/MailMessagesService.php @@ -276,6 +276,20 @@ public function createTable(int $mailContentId) 'modified' => ['type' => 'datetime', 'null' => true, 'default' => null], 'created' => ['type' => 'datetime', 'null' => true, 'default' => null], ]; + $mailFieldsTable = TableRegistry::getTableLocator()->get('BcMail.MailFields'); + $mailFields = $mailFieldsTable->find()->where(['MailFields.mail_content_id' => $mailContentId])->all(); + foreach($mailFields as $mailField) { + $fieldName = $mailField->field_name; + // 既存カラム(created/modified 等)と衝突する場合は上書きしない + if (empty($fieldName) || $fieldName === 'id' || array_key_exists($fieldName, $schema)) { + continue; + } + $schema[$fieldName] = [ + 'type' => 'text', + 'null' => true, + 'default' => null, + ]; + } $table = $this->MailMessages->createTableName($mailContentId); if ($this->BcDatabaseService->tableExists($table)) { $this->BcDatabaseService->dropTable($table); @@ -348,23 +362,24 @@ public function renameMessageField(int $mailContentId, string $oldFieldName, str */ public function construction(int $mailContentId): bool { - $mailFieldClass = TableRegistry::getTableLocator()->get('BcMail.MailFields'); - // フィールドリストを取得 - $mailFields = $mailFieldClass->find()->where(['MailFields.mail_content_id' => $mailContentId])->all(); if (!$this->BcDatabaseService->tableExists($this->MailMessages->createTableName($mailContentId))) { /* 初回の場合 */ - $this->createTable($mailContentId); - $this->construction($mailContentId); + return $this->createTable($mailContentId); } else { /* 2回目以降の場合 */ + $mailFieldsTable = TableRegistry::getTableLocator()->get('BcMail.MailFields'); + // フィールドリストを取得 + $mailFields = $mailFieldsTable->find()->where(['MailFields.mail_content_id' => $mailContentId])->all(); $messageFields = TableRegistry::getTableLocator() ->get('BaserCore.App') ->getConnection() ->getSchemaCollection() ->describe($this->MailMessages->createTableName($mailContentId))->columns(); foreach($mailFields as $mailField) { - if (!in_array($mailField->field_name, $messageFields)) { - $this->addMessageField($mailContentId, $mailField->field_name); + if (!in_array($mailField->field_name, $messageFields, true)) { + if (!$this->addMessageField($mailContentId, $mailField->field_name)) { + return false; + } } } } diff --git a/plugins/bc-mail/tests/TestCase/Service/MailMessagesServiceTest.php b/plugins/bc-mail/tests/TestCase/Service/MailMessagesServiceTest.php index c3a154baec..84c9067c62 100644 --- a/plugins/bc-mail/tests/TestCase/Service/MailMessagesServiceTest.php +++ b/plugins/bc-mail/tests/TestCase/Service/MailMessagesServiceTest.php @@ -260,17 +260,72 @@ public function testConstruction() $this->loadFixtureScenario(MailFieldsScenario::class); $MailMessagesService = $this->getService(MailMessagesServiceInterface::class); $BcDatabaseService = $this->getService(BcDatabaseServiceInterface::class); - $this->assertFalse($BcDatabaseService->columnExists('mail_message_1', 'name_1')); - $this->assertFalse($BcDatabaseService->columnExists('mail_message_1', 'name_2')); - $this->assertFalse($BcDatabaseService->columnExists('mail_message_1', 'sex')); - $this->assertTrue($MailMessagesService->construction(1)); - $this->assertTrue($BcDatabaseService->columnExists('mail_message_1', 'name_1')); - $this->assertTrue($BcDatabaseService->columnExists('mail_message_1', 'name_2')); - $this->assertTrue($BcDatabaseService->columnExists('mail_message_1', 'sex')); - $BcDatabaseService->removeColumn('mail_message_1', 'name_1'); - $BcDatabaseService->removeColumn('mail_message_1', 'name_2'); - $BcDatabaseService->removeColumn('mail_message_1', 'sex'); + $table = 'mail_message_1'; + $columns = ['name_1', 'name_2', 'sex']; + foreach ($columns as $column) { + if ($BcDatabaseService->columnExists($table, $column)) { + $BcDatabaseService->removeColumn($table, $column); + } + } + + try { + foreach ($columns as $column) { + $this->assertFalse($BcDatabaseService->columnExists($table, $column)); + } + + $this->assertTrue($MailMessagesService->construction(1)); + + foreach ($columns as $column) { + $this->assertTrue($BcDatabaseService->columnExists($table, $column)); + } + } finally { + // 他のテストへ影響しないよう、初期スキーマの状態へ戻す + $MailMessagesService->construction(1); + } + } + + /** + * フィールド数が多い場合でも初回作成で受信テーブルのカラムが不足しないこと + */ + public function testConstructionManyFieldsOnInitialCreate() + { + $this->loadFixtureScenario(MailContentsScenario::class); + $this->loadFixtureScenario(MailFieldsScenario::class); + + $MailMessagesService = $this->getService(MailMessagesServiceInterface::class); + $BcDatabaseService = $this->getService(BcDatabaseServiceInterface::class); + + $mailContentId = 100; + $table = 'mail_message_' . $mailContentId; + if ($BcDatabaseService->tableExists($table)) { + $BcDatabaseService->dropTable($table); + } + + $fieldNames = []; + for ($i = 1; $i <= 40; $i++) { + $fieldName = 'bulk_' . $i; + $fieldNames[] = $fieldName; + MailFieldsFactory::make([ + 'id' => 1000 + $i, + 'mail_content_id' => $mailContentId, + 'no' => $i, + 'field_name' => $fieldName, + 'name' => 'Bulk ' . $i, + 'type' => 'text', + 'use_field' => 1, + 'sort' => 1000 + $i, + ])->persist(); + } + + try { + $this->assertTrue($MailMessagesService->construction($mailContentId)); + foreach ($fieldNames as $fieldName) { + $this->assertTrue($BcDatabaseService->columnExists($table, $fieldName)); + } + } finally { + $this->assertTrue($MailMessagesService->dropTable($mailContentId)); + } } /**