diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php --- a/src/app/Http/Controllers/API/SignupController.php +++ b/src/app/Http/Controllers/API/SignupController.php @@ -188,7 +188,7 @@ } // Validate the verification code - $code = SignupCode::find($request->code); + $code = SignupCode::withEnvTenantContext()->find($request->code); if ( empty($code) diff --git a/src/app/Jobs/SignupVerificationEmail.php b/src/app/Jobs/SignupVerificationEmail.php --- a/src/app/Jobs/SignupVerificationEmail.php +++ b/src/app/Jobs/SignupVerificationEmail.php @@ -51,7 +51,7 @@ { \App\Mail\Helper::sendMail( new SignupVerification($this->code), - null, + $this->code->tenant_id, ['to' => $this->code->email] ); } diff --git a/src/app/Mail/SignupVerification.php b/src/app/Mail/SignupVerification.php --- a/src/app/Mail/SignupVerification.php +++ b/src/app/Mail/SignupVerification.php @@ -3,6 +3,7 @@ namespace App\Mail; use App\SignupCode; +use App\Tenant; use App\Utils; use Illuminate\Support\Str; @@ -31,8 +32,10 @@ */ public function build() { + $appName = Tenant::getConfig($this->code->tenant_id, 'app.name'); $href = Utils::serviceUrl( - sprintf('/signup/%s-%s', $this->code->short_code, $this->code->code) + sprintf('/signup/%s-%s', $this->code->short_code, $this->code->code), + $this->code->tenant_id ); $username = $this->code->first_name ?? ''; @@ -42,7 +45,7 @@ $username = trim($username); $vars = [ - 'site' => \config('app.name'), + 'site' => $appName, 'name' => $username ?: 'User', ]; diff --git a/src/app/SignupCode.php b/src/app/SignupCode.php --- a/src/app/SignupCode.php +++ b/src/app/SignupCode.php @@ -2,6 +2,7 @@ namespace App; +use App\Traits\BelongsToTenantTrait; use App\Traits\BelongsToUserTrait; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; @@ -24,12 +25,14 @@ * @property string $short_code Short validation code * @property \Carbon\Carbon $updated_at The update timestamp * @property string $submit_ip_address IP address the final signup submit request came from + * @property ?int $tenant_id Tenant identifier * @property string $verify_ip_address IP address the code verify request came from * @property ?string $voucher Voucher discount code */ class SignupCode extends Model { use SoftDeletes; + use BelongsToTenantTrait; use BelongsToUserTrait; public const SHORTCODE_LENGTH = 5; diff --git a/src/database/migrations/2024_06_13_100000_signup_codes_tenant_id.php b/src/database/migrations/2024_06_13_100000_signup_codes_tenant_id.php new file mode 100644 --- /dev/null +++ b/src/database/migrations/2024_06_13_100000_signup_codes_tenant_id.php @@ -0,0 +1,43 @@ +bigInteger('tenant_id')->unsigned()->nullable(); + $table->foreign('tenant_id')->references('id')->on('tenants')->onDelete('set null'); + } + ); + + // We could set tenant_id for old records if there's only one tenant in the DB, + // but I think nothing will happen if we don't do this. + // Leave it to the deployment-specific migrations. + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table( + 'signup_codes', + function (Blueprint $table) { + $table->dropColumn('tenant_id'); + } + ); + } +}; diff --git a/src/tests/Feature/Jobs/SignupVerificationEmailTest.php b/src/tests/Feature/Jobs/SignupVerificationEmailTest.php --- a/src/tests/Feature/Jobs/SignupVerificationEmailTest.php +++ b/src/tests/Feature/Jobs/SignupVerificationEmailTest.php @@ -5,13 +5,12 @@ use App\Jobs\SignupVerificationEmail; use App\Mail\SignupVerification; use App\SignupCode; +use App\Tenant; use Illuminate\Support\Facades\Mail; use Tests\TestCase; class SignupVerificationEmailTest extends TestCase { - private $code; - /** * {@inheritDoc} * @@ -21,11 +20,7 @@ { parent::setUp(); - $this->code = SignupCode::create([ - 'email' => 'SignupVerificationEmailTest1@' . \config('app.domain'), - 'first_name' => "Test", - 'last_name' => "Job" - ]); + SignupCode::where('email', 'SignupVerificationEmailTest1@' . \config('app.domain'))->delete(); } /** @@ -35,7 +30,9 @@ */ public function tearDown(): void { - $this->code->delete(); + SignupCode::where('email', 'SignupVerificationEmailTest1@' . \config('app.domain'))->delete(); + + parent::tearDown(); } /** @@ -45,20 +42,31 @@ */ public function testSignupVerificationEmailHandle() { + $tenant = Tenant::orderBy('id', 'desc')->first(); + $tenant->setSetting('mail.sender.address', 'sender@tenant'); + $tenant->setSetting('mail.sender.name', 'Tenant'); + + $code = new SignupCode(); + $code->email = 'SignupVerificationEmailTest1@' . \config('app.domain'); + $code->first_name = 'Test'; + $code->last_name = 'Job'; + $code->tenant_id = $tenant->id; + $code->save(); + Mail::fake(); // Assert that no jobs were pushed... Mail::assertNothingSent(); - $job = new SignupVerificationEmail($this->code); + $job = new SignupVerificationEmail($code); $job->handle(); // Assert the email sending job was pushed once Mail::assertSent(SignupVerification::class, 1); // Assert the mail was sent to the code's email - Mail::assertSent(SignupVerification::class, function ($mail) { - return $mail->hasTo($this->code->email); + Mail::assertSent(SignupVerification::class, function ($mail) use ($code) { + return $mail->hasTo($code->email) && $mail->hasFrom('sender@tenant', 'Tenant'); }); } }