Selaa lähdekoodia

パスワード設定機能 追加

master
sosuke.iwabuchi 2 vuotta sitten
vanhempi
commit
400cdcacb4
13 muutettua tiedostoa jossa 338 lisäystä ja 27 poistoa
  1. +35
    -0
      app/Email/Guests/PasswordSettingStart.php
  2. +1
    -20
      app/Http/Controllers/Web/Auth/LoginController.php
  3. +77
    -0
      app/Http/Controllers/Web/Auth/PasswordSettingStartController.php
  4. +19
    -0
      app/Http/Controllers/Web/Auth/PasswordSettingStartParam.php
  5. +45
    -0
      app/Http/Controllers/Web/Auth/PasswordSettingVerifyController.php
  6. +21
    -0
      app/Http/Controllers/Web/Auth/PasswordSettingVerifyParam.php
  7. +3
    -1
      app/Listeners/Model/UpdatingListener.php
  8. +50
    -0
      app/Logic/PasswordSettingManager.php
  9. +35
    -0
      app/Models/PasswordSettingToken.php
  10. +6
    -6
      database/migrations/2014_10_12_000000_create_users_table.php
  11. +37
    -0
      database/migrations/2023_09_22_154100_create_password_setting_tokens_table.php
  12. +6
    -0
      resources/views/emails/guests/password_setting_start.blade.php
  13. +3
    -0
      routes/api.php

+ 35
- 0
app/Email/Guests/PasswordSettingStart.php Näytä tiedosto

@@ -0,0 +1,35 @@
<?php

namespace App\Email\Guests;

use App\Models\PasswordSettingToken;

class PasswordSettingStart extends Guest
{

public function __construct(private PasswordSettingToken $token)
{
}

public function getTemplateName(): string
{
return 'emails.guests.password_setting_start';
}

public function getSubject(): string
{
return "ログインパスワード変更手続きのお知らせ";
}

public function getGuestParams(): array
{
return [
'url' => $this->getVerifyUrl(),
];
}

private function getVerifyUrl(): string
{
return $this->getAppUrl(['setting', 'password', 'verify', $this->token->token]);
}
}

+ 1
- 20
app/Http/Controllers/Web/Auth/LoginController.php Näytä tiedosto

@@ -43,9 +43,6 @@ class LoginController extends WebController
return $this->failedResponse();
}

/**
* @var Customer
*/
$customer = $customer->first();

$kintoneId = $customer->getRecordId();
@@ -66,7 +63,6 @@ class LoginController extends WebController
$user->save();
}


if (Auth::attempt([
'email' => $param->email,
'password' => $param->password,
@@ -76,22 +72,7 @@ class LoginController extends WebController
return $this->failedResponse();
}
} else {
// 初回ログインのケース
$password = "testtest";
$user = new User();
$user->email = $param->email;
$user->kintone_id = $customer->getRecordId();
$user->password = $password;
$user->kintone_customer_code = $customer->getNumber(Customer::FIELD_CUSTOMER_CODE);
$user->save();
if (Auth::attempt([
'email' => $param->email,
'password' => $password,
])) {
return $this->successResponse($customer->toArray());
} else {
return $this->failedResponse();
}
return $this->failedResponse();
}
}
}

+ 77
- 0
app/Http/Controllers/Web/Auth/PasswordSettingStartController.php Näytä tiedosto

@@ -0,0 +1,77 @@
<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Web\WebController;
use App\Kintone\Models\Customer;
use App\Logic\PasswordSettingManager;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PasswordSettingStartController extends WebController
{

public function name(): string
{
return "パスワード設定開始";
}

public function description(): string
{
return "パスワード設定手続きを開始する";
}


public function __construct(protected PasswordSettingStartParam $param, private PasswordSettingManager $manager)
{
parent::__construct();
}

protected function run(Request $request): JsonResponse
{
$param = $this->param;

$access = Customer::getAccess();
$query = Customer::getQuery()->where(Customer::FIELD_EMAIL, $param->email);

$customer = $access->some($query);

if ($customer->count() !== 1) {

// 無効なユーザだが、セキュリティ対策として成功と見せかける
return $this->successResponse();
}

$customer = $customer->first();

$kintoneId = $customer->getRecordId();

$user = User::whereKintoneId($kintoneId)
->first();

if ($user instanceof User) {
//データ同期
if ($user->email !== $param->email) {
$user->email = $param->email;
$user->save();
}
if ($user->kintone_customer_code !== $customer->getNumber(Customer::FIELD_CUSTOMER_CODE)) {
$user->kintone_customer_code = $customer->getNumber(Customer::FIELD_CUSTOMER_CODE);
$user->save();
}
} else {
// 新規の場合はユーザーを追加する
$user = new User();
$user->email = $param->email;
$user->kintone_id = $customer->getRecordId();
$user->kintone_customer_code = $customer->getNumber(Customer::FIELD_CUSTOMER_CODE);
$user->save();
}

// トークン生成
$this->manager->generate($user);

return $this->successResponse();
}
}

+ 19
- 0
app/Http/Controllers/Web/Auth/PasswordSettingStartParam.php Näytä tiedosto

@@ -0,0 +1,19 @@
<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Web\BaseParam;
use App\Http\Controllers\Web\Rule;

/**
* @property string $email
*/
class PasswordSettingStartParam extends BaseParam
{
public function rules(): array
{
return [
'email' => $this->str([...Rule::email()]),
];
}
}

+ 45
- 0
app/Http/Controllers/Web/Auth/PasswordSettingVerifyController.php Näytä tiedosto

@@ -0,0 +1,45 @@
<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Web\WebController;
use App\Kintone\Models\Customer;
use App\Logic\PasswordSettingManager;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PasswordSettingVerifyController extends WebController
{

public function name(): string
{
return "パスワード設定認証";
}

public function description(): string
{
return "パスワード設定手続きを認証する";
}


public function __construct(protected PasswordSettingVerifyParam $param, private PasswordSettingManager $manager)
{
parent::__construct();
}

protected function run(Request $request): JsonResponse
{
$param = $this->param;

$user = $this->manager->verify($param->token);
if ($user === null) {
return $this->failedResponse();
}

$user->password = $param->password;
$user->save();

return $this->successResponse();
}
}

+ 21
- 0
app/Http/Controllers/Web/Auth/PasswordSettingVerifyParam.php Näytä tiedosto

@@ -0,0 +1,21 @@
<?php

namespace App\Http\Controllers\Web\Auth;

use App\Http\Controllers\Web\BaseParam;
use App\Rules\LoginPassword;

/**
* @property string $token
* @property string $password
*/
class PasswordSettingVerifyParam extends BaseParam
{
public function rules(): array
{
return [
'token' => $this->str(),
'password' => $this->str([new LoginPassword()]),
];
}
}

+ 3
- 1
app/Listeners/Model/UpdatingListener.php Näytä tiedosto

@@ -25,7 +25,9 @@ class UpdatingListener extends ModelListener
// ログインパスワードのハッシュ化
if ($event->model instanceof User) {
if ($event->model->isDirty(User::COL_NAME_PASSWORD)) {
$event->model->password = Hash::make($event->model->password);
if ($event->model->password !== null) {
$event->model->password = Hash::make($event->model->password);
}
}
}



+ 50
- 0
app/Logic/PasswordSettingManager.php Näytä tiedosto

@@ -0,0 +1,50 @@
<?php

namespace App\Logic;

use App\Email\Guests\PasswordSettingStart;
use App\Models\PasswordSettingToken;
use App\Models\User;
use App\Util\DateUtil;
use Illuminate\Support\Str;

class PasswordSettingManager
{

public function __construct()
{
}

public function generate(User $user)
{
// トークン生成
$model = new PasswordSettingToken();
$model->user_id = $user->id;
$model->token = Str::uuid();
$model->expires_at = DateUtil::now()->addHours(24);
$model->save();

// メール送信
$email = (new PasswordSettingStart($model))
->setEmail($user->email);
$emailManager = new EmailManager($email);
$emailManager->confirm();
}

public function verify(string $token): User|null
{
$model = PasswordSettingToken::whereToken($token)
->expiresIn()
->first();

if ($model === null) {
return null;
}

$user = User::whereId($model->user_id)->firstOrFail();

$model->delete();

return $user;
}
}

+ 35
- 0
app/Models/PasswordSettingToken.php Näytä tiedosto

@@ -0,0 +1,35 @@
<?php

namespace App\Models;

use App\Models\Feature\UserId;
use App\Util\DateUtil;
use Illuminate\Database\Eloquent\Builder;

class PasswordSettingToken extends AppModel
{
use UserId;

const COL_NAME_USER_ID = ColumnName::USER_ID;
const COL_NAME_TOKEN = 'token';
const COL_NAME_EXPIRES_AT = 'expires_at';

protected $casts = [
self::COL_NAME_EXPIRES_AT => 'datetime',
];

public function getHistory(): ?HistoryModel
{
return null;
}

public function getModelName(): string
{
return "ログインパスワード設定トークン";
}

public function scopeExpiresIn(Builder $query)
{
return $query->where(self::COL_NAME_EXPIRES_AT, '>', DateUtil::now());
}
}

+ 6
- 6
database/migrations/2014_10_12_000000_create_users_table.php Näytä tiedosto

@@ -16,9 +16,9 @@ return new class extends Migration
$helper = new MigrationHelper($table);
$helper->baseColumn();
$table->string('email')->unique()->comment('Email');
$table->string('password')->comment('ログインパスワード');
$table->string('kintone_id')->comment('KintoneID');
$table->string('kintone_customer_code')->comment('顧客コード');
$table->string('password')->nullable()->comment('ログインパスワード');
$table->string('kintone_id')->nullable()->comment('KintoneID');
$table->string('kintone_customer_code')->nullable()->comment('顧客コード');

$helper->index(1, ['email']);
$helper->index(2, ['kintone_id']);
@@ -29,9 +29,9 @@ return new class extends Migration
$helper->baseColumn();

$table->string('email')->comment('Email');
$table->string('password')->comment('ログインパスワード');
$table->string('kintone_id')->comment('KintoneID');
$table->string('kintone_customer_code')->comment('顧客コード');
$table->string('password')->nullable()->comment('ログインパスワード');
$table->string('kintone_id')->nullable()->comment('KintoneID');
$table->string('kintone_customer_code')->nullable()->comment('顧客コード');

$helper->index(1, ['email']);
$helper->index(2, ['kintone_id']);


+ 37
- 0
database/migrations/2023_09_22_154100_create_password_setting_tokens_table.php Näytä tiedosto

@@ -0,0 +1,37 @@
<?php

use App\Models\ColumnName;
use App\Util\MigrationHelper;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('password_setting_tokens', function (Blueprint $table) {
$helper = new MigrationHelper($table);
$helper->baseColumn();

$table->uuid(ColumnName::USER_ID)->unique()->comment('ユーザーID');
$table->uuid('token')->unique()->comment('トークン');
$table->string('expires_at')->comment('有効期限');

$helper->index(1, [ColumnName::USER_ID]);
$helper->index(3, ['token']);
$helper->index(4, ['expires_at']);
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('email_change_tokens');
}
};

+ 6
- 0
resources/views/emails/guests/password_setting_start.blade.php Näytä tiedosto

@@ -0,0 +1,6 @@
@extends('emails.layouts.guest')

@section('contents')
こちらのURLにアクセスし、ログインパスワードの変更手続きを進めてください。
{{ $url }}
@endsection

+ 3
- 0
routes/api.php Näytä tiedosto

@@ -34,3 +34,6 @@ RouteHelper::post('/ask', App\Http\Controllers\Web\FAQ\AskController::class);

RouteHelper::post('/email/change/start', App\Http\Controllers\Web\Customer\ChangeEmailStartController::class);
RouteHelper::post('/email/change/verify', App\Http\Controllers\Web\Customer\ChangeEmailVerifyController::class);

RouteHelper::post('/password/setting/start', App\Http\Controllers\Web\Auth\PasswordSettingStartController::class);
RouteHelper::post('/password/setting/verify', App\Http\Controllers\Web\Auth\PasswordSettingVerifyController::class);

Loading…
Peruuta
Tallenna