領収証発行サービス
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

406 rindas
11KB

  1. <?php
  2. namespace App\Http\Controllers\Web;
  3. use App\Codes\HTTPResultCode as ResultCode;
  4. use App\Codes\UserRole;
  5. use App\Exceptions\AppCommonException;
  6. use App\Exceptions\ExclusiveException;
  7. use App\Exceptions\GeneralErrorMessageException;
  8. use App\Util\DBUtil;
  9. use Exception;
  10. use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
  11. use Illuminate\Foundation\Bus\DispatchesJobs;
  12. use Illuminate\Foundation\Validation\ValidatesRequests;
  13. use Illuminate\Http\JsonResponse;
  14. use Illuminate\Http\Request;
  15. use Illuminate\Http\Response;
  16. use Illuminate\Routing\Controller as BaseController;
  17. use Illuminate\Support\Arr;
  18. use Illuminate\Support\Facades\Auth;
  19. use Illuminate\Support\Facades\Log;
  20. use Illuminate\Support\Facades\Validator;
  21. use Illuminate\Support\Str;
  22. use Illuminate\Validation\ValidationException;
  23. use LogicException;
  24. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  25. use Symfony\Component\HttpKernel\Exception\HttpException;
  26. abstract class WebController extends BaseController
  27. {
  28. use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
  29. const COL_NAME_CREATED_AT = 'created_at';
  30. const COL_NAME_UPDATED_AT = 'updated_at';
  31. const COL_NAME_RESULT_CODE = 'result';
  32. const COL_NAME_DATA = 'data';
  33. const COL_NAME_MESSAGES = 'messages';
  34. const COL_NAME_GENERAL_MESSAGE = 'general';
  35. const COL_NAME_EMAIL_ID = 'email_id';
  36. const COL_NAME_ERRORS = 'errors';
  37. /**
  38. * バリデートした結果を格納
  39. *
  40. * @var array
  41. */
  42. protected $validated = [];
  43. /**
  44. * 画面へ返却するメールID
  45. *
  46. * @var integer|null
  47. */
  48. private int|null $emailId = null;
  49. /**
  50. * 返却するメッセージ
  51. *
  52. * @var array|null
  53. */
  54. private array|null $messages = null;
  55. /**
  56. * 返却するメッセージ
  57. *
  58. * @var string|null
  59. */
  60. private string|null $generalMessage = null;
  61. /**
  62. * 返却するデータ
  63. *
  64. * @var mixed|null
  65. */
  66. private $data = null;
  67. protected DBUtil $transaction;
  68. /**
  69. * 返却する結果コード
  70. *
  71. * @var ResultCode|null
  72. */
  73. private ResultCode|null $resultCode = ResultCode::SECCESS;
  74. public function __construct()
  75. {
  76. $this->transaction = DBUtil::instance();
  77. }
  78. /**
  79. * パラメータオブジェクト
  80. */
  81. protected function getParam(): IParam
  82. {
  83. return $this->param;
  84. }
  85. /**
  86. * コントローラーの名前
  87. * オーバーライドされることを想定
  88. * 主に、Routeのドキュメント作成用
  89. *
  90. * @return string
  91. */
  92. public function name(): string
  93. {
  94. return "---未設定---";
  95. }
  96. /**
  97. * コントローラーの説明
  98. * オーバーライドされることを想定
  99. * 主に、Routeのドキュメント作成用
  100. *
  101. * @return string
  102. */
  103. public function description(): string
  104. {
  105. return "---未設定---";
  106. }
  107. /**
  108. * オーバーライド必要
  109. * メインロジック
  110. *
  111. * @param Request $request
  112. * @return Response|JsonResponse|string
  113. */
  114. protected function run(Request $request): Response|JsonResponse|BinaryFileResponse|string
  115. {
  116. return $this->successResponse();
  117. }
  118. private function getRules()
  119. {
  120. return $this->getParam()->rules();
  121. }
  122. public function entry(Request $request)
  123. {
  124. $this->setLogContext($request);
  125. try {
  126. $validator = Validator::make($request->all(), $this->getRules());
  127. $validator->validate();
  128. } catch (ValidationException $e) {
  129. logger("validate error", ['errors' => $e->errors(), 'request' => $request->all(), 'path' => $request->path()]);
  130. return $this->validateErrorResponse($e);
  131. }
  132. try {
  133. $this->validated = $validator->validated();
  134. $this->getParam()->setData($this->validated);
  135. $this->authorize();
  136. return $this->run($request);
  137. } catch (GeneralErrorMessageException $e) {
  138. return $this->failedResponse([], $e->getMessage());
  139. } catch (AppCommonException $e) {
  140. logs()->error(sprintf("Appエラー:%s", $e->getMessage()));
  141. return $this->failedResponse();
  142. } catch (ExclusiveException $e) {
  143. logs()->error(sprintf("排他エラー:%s", $e->getMessage()));
  144. return $this->exclusiveErrorResponse();
  145. } catch (LogicException $e) {
  146. logs()->error([
  147. sprintf("実装エラー:%s", $e->getMessage()),
  148. get_class($e),
  149. $e->getFile(),
  150. $e->getLine(),
  151. $request->all(),
  152. ]);
  153. logger(array_filter($e->getTrace(), function ($val, $key) {
  154. return $key <= 5;
  155. }, ARRAY_FILTER_USE_BOTH));
  156. return $this->failedResponse();
  157. } catch (ValidationException $e) {
  158. return $this->validateErrorResponse($e);
  159. } catch (HttpException $e) {
  160. if ($e->getStatusCode() === 401) {
  161. return $this->unAuthorizedResponse();
  162. }
  163. throw e;
  164. } catch (Exception $e) {
  165. logs()->error([
  166. sprintf("例外エラー:%s", $e->getMessage()),
  167. get_class($e),
  168. $e->getFile(),
  169. $e->getLine(),
  170. $request->all(),
  171. ]);
  172. logger(array_filter($e->getTrace(), function ($val, $key) {
  173. return $key <= 5;
  174. }, ARRAY_FILTER_USE_BOTH));
  175. return $this->failedResponse();
  176. }
  177. }
  178. protected function successResponse(array|object $data = [], array|string $messages = [])
  179. {
  180. return $this->setData($data)
  181. ->setMessages($messages)
  182. ->setResultCode(ResultCode::SECCESS)
  183. ->makeResponse();
  184. }
  185. protected function failedResponse(array|object $data = [], array|string $messages = [])
  186. {
  187. return $this->setData($data)
  188. ->setMessages($messages)
  189. ->setResultCode(ResultCode::FAILED)
  190. ->makeResponse();
  191. }
  192. protected function unAuthorizedResponse(array|object $data = [], array|string $messages = [])
  193. {
  194. return $this->setData($data)
  195. ->setMessages($messages)
  196. ->setResultCode(ResultCode::UNAUTHORIZED)
  197. ->makeResponse();
  198. }
  199. protected function exclusiveErrorResponse(array|object $data = [], array|string $messages = [])
  200. {
  201. return $this->setData($data)
  202. ->setMessages($messages)
  203. ->setResultCode(ResultCode::EXCLUSIVE_ERROR)
  204. ->makeResponse();
  205. }
  206. protected function validateErrorResponse(ValidationException|array $exception, string|null $generalMessage = null)
  207. {
  208. $errorMessages = [];
  209. $general = null;
  210. if ($exception instanceof ValidationException) {
  211. foreach ($exception->errors() as $key => $m) {
  212. $errorMessages[$key] = $m[0];
  213. }
  214. }
  215. if (is_array($exception)) {
  216. $errorMessages = $exception;
  217. }
  218. $general = $generalMessage ?? data_get($errorMessages, self::COL_NAME_GENERAL_MESSAGE);
  219. return $this->setData([])
  220. ->setMessages($errorMessages)
  221. ->setGeneralMessage($general)
  222. ->setResultCode(ResultCode::FAILED)
  223. ->makeResponse();
  224. }
  225. private function makeResponse()
  226. {
  227. if ($this->resultCode === null) {
  228. abort(403);
  229. }
  230. $ret = [];
  231. Arr::set($ret, self::COL_NAME_RESULT_CODE, $this->resultCode->value);
  232. if ($this->data !== null) {
  233. Arr::set($ret, self::COL_NAME_DATA, $this->data);
  234. }
  235. if ($this->messages !== null) {
  236. Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_ERRORS, $this->messages);
  237. }
  238. if ($this->generalMessage !== null) {
  239. Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_GENERAL_MESSAGE, $this->generalMessage);
  240. }
  241. if ($this->emailId !== null) {
  242. Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_EMAIL_ID, $this->emailId);
  243. }
  244. if (request()->wantsJson()) {
  245. return response()
  246. ->json($ret)
  247. ->withHeaders($this->makeHeader());
  248. } else {
  249. abort(500);
  250. }
  251. }
  252. private function makeHeader(): array
  253. {
  254. $header = [];
  255. $user = Auth::user();
  256. if ($user) {
  257. $header["App-User-Auth"] = sprintf("%d,%d", $user->id, $user->role->value);
  258. } else {
  259. $header["App-User-Auth"] = 'none';
  260. }
  261. return $header;
  262. }
  263. // 以下 認可関係
  264. protected array|null $roleAllow = null;
  265. protected array|null $roleDisallow = null;
  266. protected array|null $customAllow = null;
  267. protected function roleAllow(UserRole $role)
  268. {
  269. $this->roleAllow = [];
  270. foreach (UserRole::cases() as $ele) {
  271. if ($role->value <= $ele->value) {
  272. $this->roleAllow[] = $ele;
  273. }
  274. }
  275. }
  276. private function authorize()
  277. {
  278. if (!Auth::check()) {
  279. return;
  280. }
  281. $role = Auth::user()->role;
  282. if (!$this->canAccess($role)) {
  283. abort(401);
  284. }
  285. }
  286. public function canAccess(UserRole $role)
  287. {
  288. if (is_array($this->roleAllow) && !in_array($role, $this->roleAllow)) {
  289. return false;
  290. }
  291. if (is_array($this->roleDisallow) && in_array($role, $this->roleDisallow)) {
  292. return false;
  293. }
  294. return $this->canCustomAccess();
  295. }
  296. public function canCustomAccess(): bool
  297. {
  298. if (Auth::user()->role === UserRole::SUPER_ADMIN) {
  299. return true;
  300. }
  301. if ($this->customAllow === null) {
  302. return true;
  303. }
  304. $myCustoms = Auth::user()->contract->custom();
  305. foreach ($this->customAllow as $targetCustom) {
  306. if (in_array($targetCustom, $myCustoms, true)) {
  307. return true;
  308. }
  309. }
  310. return false;
  311. }
  312. // 返却用データの登録
  313. protected function setEmailId(int $emailId)
  314. {
  315. $this->emailId = $emailId;
  316. return $this;
  317. }
  318. protected function setMessages(array|string $messages)
  319. {
  320. if (is_array($messages)) {
  321. $this->messages = $messages;
  322. } else {
  323. $this->setGeneralMessage($messages);
  324. }
  325. return $this;
  326. }
  327. protected function setGeneralMessage(string|null $generalMessage)
  328. {
  329. $this->generalMessage = $generalMessage;
  330. return $this;
  331. }
  332. protected function setData($data)
  333. {
  334. $this->data = $data;
  335. return $this;
  336. }
  337. protected function setResultCode(ResultCode $resultCode)
  338. {
  339. $this->resultCode = $resultCode;
  340. return $this;
  341. }
  342. protected function setLogContext(Request $request)
  343. {
  344. Log::withContext([
  345. '__requestUuid__' => strval(Str::uuid()),
  346. '__userId__' => Auth::id(),
  347. '__path__' => $request->path(),
  348. ]);
  349. }
  350. }