Ver código fonte

ログインユーザー一覧機能等追加

develop
sosuke.iwabuchi 2 anos atrás
pai
commit
8dfae71477
12 arquivos alterados com 471 adições e 6 exclusões
  1. +74
    -0
      app/Http/Controllers/Web/LoginUser/CreateController.php
  2. +26
    -0
      app/Http/Controllers/Web/LoginUser/CreateParam.php
  3. +63
    -0
      app/Http/Controllers/Web/LoginUser/LoginUsersController.php
  4. +28
    -0
      app/Http/Controllers/Web/LoginUser/LoginUsersParam.php
  5. +4
    -0
      app/Http/Controllers/Web/WebController.php
  6. +146
    -0
      app/Logic/User/LoginUserManager.php
  7. +17
    -1
      app/Models/User.php
  8. +81
    -0
      app/Repositories/LoginUserRepository.php
  9. +10
    -0
      app/Repositories/LoginUserRepositoryData.php
  10. +10
    -5
      database/migrations/2023_04_15_150500_create_users_table.php
  11. +8
    -0
      database/seeders/TestUserSeeder.php
  12. +4
    -0
      routes/api.php

+ 74
- 0
app/Http/Controllers/Web/LoginUser/CreateController.php Ver arquivo

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

namespace App\Http\Controllers\Web\LoginUser;

use App\Codes\UserRole;
use App\Exceptions\AppCommonException;
use App\Features\LoginUser;
use App\Http\Controllers\Web\IParam;
use App\Http\Controllers\Web\WebController;
use App\Logic\User\LoginUserManager;
use App\Repositories\LoginUserRepository;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class CreateController extends WebController
{

use LoginUser;

public function name(): string
{
return "ログインユーザー一覧取得";
}

public function description(): string
{
return "ログインユーザー一覧を取得する";
}

public function __construct(
protected CreateParam $param,
private LoginUserManager $manager
) {
parent::__construct();
$this->roleAllow(UserRole::CONTRACT_ADMIN);
}

protected function getParam(): IParam
{
return $this->param;
}

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


try {
$this->transaction->beginTransaction();


$currentContract = $this->loginUser()->getCurrentContract();
if (!$currentContract) {
throw new AppCommonException("認証不正");
}

$messages = $this->manager->initForCreate($currentContract)
->fill($param->toArray())
->create();

if (count($messages) !== 0) {
$this->transaction->rollBack();
return $this->validateErrorResponse($messages);
}

$this->transaction->commit();
} catch (Exception $e) {
$this->transaction->rollBack();
throw $e;
}

return $this->successResponse();
}
}

+ 26
- 0
app/Http/Controllers/Web/LoginUser/CreateParam.php Ver arquivo

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

namespace App\Http\Controllers\Web\LoginUser;

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

/**
* @property string $email
* @property string $name
* @property string $password
*/

class CreateParam extends BaseParam
{
public function rules(): array
{
return
[
User::COL_NAME_EMAIL => $this->str(['email:dns']),
User::COL_NAME_NAME => $this->str(),
User::COL_NAME_PASSWORD => $this->str([new LoginPassword()]),
];
}
}

+ 63
- 0
app/Http/Controllers/Web/LoginUser/LoginUsersController.php Ver arquivo

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

namespace App\Http\Controllers\Web\LoginUser;

use App\Codes\UserRole;
use App\Exceptions\AppCommonException;
use App\Features\LoginUser;
use App\Http\Controllers\Web\IParam;
use App\Http\Controllers\Web\WebController;
use App\Repositories\LoginUserRepository;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class LoginUsersController extends WebController
{

use LoginUser;

public function name(): string
{
return "ログインユーザー一覧取得";
}

public function description(): string
{
return "ログインユーザー一覧を取得する";
}

public function __construct(
protected LoginUsersParam $param,
private LoginUserRepository $repository
) {
parent::__construct();
$this->roleAllow(UserRole::CONTRACT_ADMIN);
}

protected function getParam(): IParam
{
return $this->param;
}

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

$currentContractId = $this->loginUser()->getCurrentContractId();
if (!$currentContractId) {
throw new AppCommonException("認証不正");
}

$condition = [
...$param->toArray(),
LoginUserRepository::CONDITION_CONTRACT_ID => $currentContractId,
];

$list = $this->repository->get($condition);


return $this->successResponse([
'records' => $list
]);
}
}

+ 28
- 0
app/Http/Controllers/Web/LoginUser/LoginUsersParam.php Ver arquivo

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

namespace App\Http\Controllers\Web\LoginUser;

use App\Http\Controllers\Web\BaseParam;
use App\Repositories\LoginUserRepository as Repository;

/**
* @property ?string $id
* @property ?string $name
* @property ?string $email
*/

class LoginUsersParam extends BaseParam
{
public function rules(): array
{
return
array_merge(
[
Repository::CONDITION_ID => $this->str(true),
Repository::CONDITION_NAME => $this->str(true),
Repository::CONDITION_EMAIL => $this->str(true),
],
$this->sortableRules(),
);
}
}

+ 4
- 0
app/Http/Controllers/Web/WebController.php Ver arquivo

@@ -7,6 +7,7 @@ use App\Codes\UserRole;
use App\Exceptions\AppCommonException;
use App\Exceptions\ExclusiveException;
use App\Exceptions\GeneralErrorMessageException;
use App\Util\DBUtil;
use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
@@ -74,6 +75,8 @@ abstract class WebController extends BaseController
*/
private $data = null;

protected DBUtil $transaction;

/**
* 返却する結果コード
*
@@ -83,6 +86,7 @@ abstract class WebController extends BaseController

public function __construct()
{
$this->transaction = DBUtil::instance();
}




+ 146
- 0
app/Logic/User/LoginUserManager.php Ver arquivo

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

namespace App\Logic\User;

use App\Codes\UserRole;
use App\Models\Contract;
use App\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use LogicException;

class LoginUserManager
{

private bool $initialized = false;

private User $user;
private Contract $contract;

public function __construct()
{
}

public function initForCreate(string|Contract $contractId)
{
$this->setContract($contractId);
$this->setUser(null);
$this->initialized = true;
return $this;
}

public function initForModify(string|Contract $contractId, string|User $userId)
{
$this->setContract($contractId);
$this->setUser($userId);
$this->initialized = true;
return $this;
}

public function getTimestamp(): Carbon
{
if (!$this->initialized) {
throw new LogicException("初期化不正");
}
return $this->user->updated_at < $this->contract->updated_at ? $this->contract->updated_at : $this->user->updated_at;
}

public function fill(array $attr)
{
if (!$this->initialized) {
throw new LogicException("初期化不正");
}
$this->user->fill($attr);
return $this;
}

public function create(): array
{
$messages = $this->checkParam();

if (count($messages) !== 0) {
return $messages;
}

$this->user->save();
return [];
}
public function update(): array
{
$messages = $this->checkParam();

if (count($messages) !== 0) {
return $messages;
}

$this->user->save();
return [];
}

private function setContract(string|Contract $contractId)
{
if ($contractId instanceof Contract) {
$this->contract = $contractId;
$this->initialized = true;
return;
}

$this->contract = Contract::findOrFail($contractId);
$this->initialized = true;
return;
}

private function setUser(string|User|null $userId)
{
if ($userId instanceof User) {
$this->user = $userId;
return;
} else if (is_string($userId)) {
$this->user = User::findOrFail($userId);
return;
}

$this->user = new User();
$this->user->setContract($this->contract);
$this->user->role = UserRole::NORMAL_ADMIN;
}

private function checkParam()
{
$validator = Validator::make($this->user->toArray(), []);

if ($validator->failed()) {
throw new LogicException("バリデートエラー");
}

$messages = [];

$this->checkEmailUnique($messages);
$this->passwordEncrypto($messages);

return $messages;
}

private function passwordEncrypto(array &$messages)
{
if ($this->user->isDirty(User::COL_NAME_PASSWORD)) {
$this->user->password = Hash::make($this->user->password);
}
}

private function checkEmailUnique(array &$messages)
{
if ($this->user->isDirty(User::COL_NAME_EMAIL)) {

$exists = User::whereEmail($this->user->email)
->where(User::COL_NAME_ID, '<>', $this->user->id)
->exists();

if ($exists) {
$messages[User::COL_NAME_EMAIL] = trans('validation.unique');
}
}
}
}

+ 17
- 1
app/Models/User.php Ver arquivo

@@ -24,6 +24,13 @@ class User extends Authenticatable implements IModelFeature
const COL_NAME_ROLE = 'role';
const COL_NAME_EMAIL = 'email';
const COL_NAME_NAME = 'name';
const COL_NAME_PASSWORD = 'password';

const COL_NAME_CREATED_BY = ColumnName::CREATED_BY;
const COL_NAME_UPDATED_BY = ColumnName::UPDATED_BY;
const COL_NAME_CREATED_AT = ColumnName::CREATED_AT;
const COL_NAME_UPDATED_AT = ColumnName::UPDATED_AT;
const COL_NAME_DELETED_AT = ColumnName::DELETED_AT;

/**
* The attributes that should be hidden for serialization.
@@ -31,7 +38,16 @@ class User extends Authenticatable implements IModelFeature
* @var array<int, string>
*/
protected $hidden = [
'password',
self::COL_NAME_PASSWORD,
];

protected $guarded = [
self::COL_NAME_ID,
self::COL_NAME_CREATED_BY,
self::COL_NAME_UPDATED_BY,
self::COL_NAME_CREATED_AT,
self::COL_NAME_UPDATED_AT,
self::COL_NAME_DELETED_AT,
];

protected $casts = [


+ 81
- 0
app/Repositories/LoginUserRepository.php Ver arquivo

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

namespace App\Repositories;

use App\Models\User;
use App\Repositories\BaseRepository;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class LoginUserRepository extends BaseRepository
{

const CONDITION_ID = 'id';

const CONDITION_NAME = 'name';
const CONDITION_ROLE = 'role';
const CONDITION_EMAIL = 'email';
const CONDITION_CONTRACT_ID = 'contract_id';

const TABLE_USER = "user";


/**
* コレクションを取得する
*
* @param array $condition
* @return Collection<LoginUserRepositoryData>
*/
public function get(array $condition): Collection
{
$table = User::getBuilder(static::TABLE_USER);


// -----検索条件
// ID
$this->where($table, $condition, static::CONDITION_ID, $this->makeColumnName([static::TABLE_USER, User::COL_NAME_ID]));

// 名前
$name = data_get($condition, static::CONDITION_NAME);
if ($name) {
$table->where($this->makeColumnName([static::TABLE_USER, User::COL_NAME_NAME]), 'like', "%{$name}%");
}

// EMAIL
$email = data_get($condition, static::CONDITION_EMAIL);
if ($email) {
$table->where($this->makeColumnName([static::TABLE_USER, User::COL_NAME_EMAIL]), 'like', "%{$email}%");
}
// 契約ID
$this->where($table, $condition, static::CONDITION_CONTRACT_ID, $this->makeColumnName([static::TABLE_USER, User::COL_NAME_CONTRACT_ID]));

$table->select($this->columns());

$main = DB::table($table, "main");

// ソート
$this->sort($main, $condition);
$main->orderBy(static::CONDITION_ID);

// リミット
$this->limit($main, $condition);


return LoginUserRepositoryData::makeList($main->get());
}

private function columns()
{
$user = static::TABLE_USER;
$columns = [
$this->makeColumnNameForSelect([$user, User::COL_NAME_ID]),
$this->makeColumnNameForSelect([$user, User::COL_NAME_NAME]),
$this->makeColumnNameForSelect([$user, User::COL_NAME_ROLE]),
$this->makeColumnNameForSelect([$user, User::COL_NAME_EMAIL]),
$this->makeColumnNameForSelect([$user, User::COL_NAME_UPDATED_AT]),
];


return $columns;
}
}

+ 10
- 0
app/Repositories/LoginUserRepositoryData.php Ver arquivo

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

namespace App\Repositories;


/**
*/
class LoginUserRepositoryData extends BaseRepositoryData
{
}

+ 10
- 5
database/migrations/2023_04_15_150500_create_users_table.php Ver arquivo

@@ -14,8 +14,8 @@ return new class extends Migration
public function up(): void
{

MigrationHelper::createTable('users', $this->schema());
MigrationHelper::createTable('user_histories', $this->schema());
MigrationHelper::createTable('users', $this->schema(false));
MigrationHelper::createTable('user_histories', $this->schema(true));
}

/**
@@ -27,10 +27,10 @@ return new class extends Migration
Schema::dropIfExists('user_histories');
}

private function schema()
private function schema(bool $forHistory)
{

return function (Blueprint $table, MigrationHelper $helper) {
return function (Blueprint $table, MigrationHelper $helper) use ($forHistory) {
$helper->baseColumn()
->contractId();

@@ -41,7 +41,12 @@ return new class extends Migration


$helper->index(1, [ColumnName::CONTRACT_ID]);
$helper->index(2, ['email']);

if ($forHistory) {
$helper->index(2, ['email']);
} else {
$helper->unique(1, ['email']);
}
};
}
};

+ 8
- 0
database/seeders/TestUserSeeder.php Ver arquivo

@@ -52,5 +52,13 @@ class TestUserSeeder extends Seeder
User::COL_NAME_NAME => $email . "太郎",
]);
}
$email = 'hello-admin@aa.com';
if (!User::whereEmail($email)->exists()) {
User::factory()->for($contract)->create([
User::COL_NAME_EMAIL => $email,
User::COL_NAME_ROLE => UserRole::CONTRACT_ADMIN,
User::COL_NAME_NAME => $email . "太郎",
]);
}
}
}

+ 4
- 0
routes/api.php Ver arquivo

@@ -30,6 +30,10 @@ RouteHelper::get('/receipt/download', App\Http\Controllers\Web\ReceiptIssuingOrd
RouteHelper::get('/contracts', App\Http\Controllers\Web\Contract\ContractsController::class);


RouteHelper::get('/users', App\Http\Controllers\Web\LoginUser\LoginUsersController::class);
RouteHelper::post('/user/create', App\Http\Controllers\Web\LoginUser\CreateController::class);


// Custom for HelloTechno
RouteHelper::get('/custom/hello-techno/customers', App\Http\Controllers\Web\Custom\HelloTechno\CustomersController::class);
RouteHelper::get('/custom/hello-techno/parkings', App\Http\Controllers\Web\Custom\HelloTechno\ParkingsController::class);


Carregando…
Cancelar
Salvar