[Laravel8.16.0] 一般権限と管理者権限で表示制御

mysql> describe users;
+—————————+—————–+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+—————————+—————–+——+—–+———+—————-+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
| email_verified_at | timestamp | YES | | NULL | |
| password | varchar(255) | NO | | NULL | |
| two_factor_secret | text | YES | | NULL | |
| two_factor_recovery_codes | text | YES | | NULL | |
| remember_token | varchar(100) | YES | | NULL | |
| current_team_id | bigint unsigned | YES | | NULL | |
| profile_photo_path | text | YES | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
| role_id | int | NO | | NULL | |
+—————————+—————–+——+—–+———+—————-+

$ php artisan make:middleware IsAdmin

app/Http/Middleware/Kernel.php

protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'IsAdmin'=>\App\Http\Middleware\IsAdmin::class,
    ];

app/Models/Users.php

public function isAdmin(){
        if($this->role_id == 1){
            return true;
        }
        return false;
    }

route

Route::get('/', function () {

	$user = Auth:: user();

	if($user->isAdmin()){
		echo "this user is admin";
	}
    // return view('welcome');
});

挙動確認

isAdmin.php

use Illuminate\Support\Facades\Auth;
public function handle(Request $request, Closure $next)
    {
        $user = Auth::user();
        if(!$user->isAdmin()){
            return redirect()->intended('/');
        }
        return $next($request);
    }

$ php artisan make:controller AdminController

AdminController.php

public function __construct(){
        $this->middleware('IsAdmin');
    }
 
    public function index(){
        return view('admin.index');
    }

route

use App\Http\Controllers\AdminController;
Route::get('/admin', [App\Http\Controllers\AdminController::class, 'index']);

もしくはrouteで制御

Route::group(['middleware' => ['auth','IsAdmin'] ], function(){
 	Route::get('/admin', [App\Http\Controllers\AdminController::class, 'index']);
 });

思い出したーーーーーー

[Design Guideline] 用語 : ポジネガ、DICカラー、アイソレーション

### ポジ表示、ネガ表示
-ネガは陰画、ポジは陽画
-実際の明暗とは逆になっている画像で、明るい所が黒く、暗い所が白い画像

元画像

photoshopで画像を開く

photoshop [command + i]

DICカラー
L DIC社が提供

アイソレーション
– 全体1に対して、余白0.5と言われている

変形(長体・平体・斜体・回転)、間隔の変更、書体の変更、色の変更、装飾(影・縁取り・立体表示)、アイソレーション範囲内での他要素の表示、視認性を低下させる背景の使用、文中での使用

用語知らないと、ビビりまくるな

[Laravel8.16.0] ユーザ登録のテストコードを書く

$ cp .env.example .env.testing
$ php artisan key:generate –env=testing
// test用のDB接続
$ vi .env.testing

$ rm ./tests/Feature/ExampleTest.php
$ rm ./tests/Unit/ExampleTest.php

app/Actions/Fortify/CreateNewUser.php

return User::create([
            'name' => $input['name'],
            'company' => $input['company'],
            'role_id' => 1,
            'email' => $input['email'],
            'password' => Hash::make($input['password']),
        ]);

CreateNewUser.phpと同じようなことを書いていく
$ php artisan make:test UserRegisterTest

tests/Feature/UserRegisterTest.php

public function testUserRegister()
    {
        $email = 'hogehoge@gmail.com';
        $this->post(route('register'), [
            'name' => 'testuser',
            'company' => 'test company',
            'email' => $email,
            'password' => 'password',
            'password_confirmation' => 'password'
        ])
            ->assertStatus(302);
 
        $this->assertDatabaseHas('users', ['email' => $email]);
    }

$ vendor/bin/phpunit –testdox
PHPUnit 9.4.3 by Sebastian Bergmann and contributors.

User Register (Tests\Feature\UserRegister)
✔ User register

Time: 00:00.354, Memory: 26.00 MB

OK (1 test, 2 assertions)

なるほど、わかったようなわかってないようなw

[JavaScript] ES2020のconst, let, var

strict

'use strict'; // 厳密なエラーチェック

定数 // 再代入不可

		const price = 10;
		console.log(price * 3);

変数 // letを使う varは古い書き方

		let price = 10;
		price = 30;
		console.log(price * 3);

無名関数

const sum = function(a, b, c){
			return a + b + c;
		}
		const total = sum(1, 2, 3) + sum(4, 5, 6);
		console.log(total);

arrow function

const sum = (a, b, c) => a + b + c;

テストコードの方針を考える

### テストコードの目的
– テストなしにリリースするのが不安な時
– 保守性の向上
– 障害時に不具合をテストコードで再現する

### テストコードの対象
– セキュリティ上重要な箇所(権限管理、決済、メール)
– 重要度の高いユースケース
– 複雑なロジックやトリッキーなコード
– 止むを得ずパッチを当てたところ
– 自動化した方が早いところ(手作業でのアカウント作成などを省略する)
– 例外処理(意図的にバグを発生させる時)
※シンプルなロジックや重要度の低いコードのテストは優先度が下げるか省略も検討する

### テストコードの留意点
– 閾値の境界、条件分岐の網羅
– before afterを検証する
– テストコードはシンプルにする
– privateメソッドはテストしない

なるほど、枠組みは大体理解しました。

[front coding guideline]一応作っておく

一個作っておいて、追加/加筆することで、ノウハウを蓄積していく。

## 目次
– 方針
– マークアップ(HTML)
– スタイルシート
– 画像スライス
– SP対応
– フォーム
– その他
– 表示速度の改善
– その他

### 作っていく中で気になった点
ID・Class名
L 原則としてBEM+FLOCSSのルールに従って命名

CSS プロパティの順序

box-sizing
margin、padding
width、min-width、max-width
height、min-height、max-height
background、background-color、background-image、background-repoeat、background-position、background-size
border、border-width、border-style、border-color、border-radius
outline、outline-width、outline-style、outline-color
table-layout、border-collapse、border-spacing、empty-cells、caption-side
box-shadow
list-style、list-style-type、list-style-image、list-style-position
overflow
opacity、visibility
display、box-flex
float、clear
position、top、right、bottom、left、z-index
color
font-size、font-weight、font-style、line-height、letter-spacing
text-align、text-decoration、text-shadow
vertical-align
content
zoom
その他

フォント周りの単位指定
L font-size:remで指定

PNG-32(24)
L 透過色がある画像に使用

画像ファイルの圧縮
L compressor.ioを使う

ちょっとずつクオリティを上げていきたいですね。JSの最新版の書き方もやっておかないといけないな。
よし、次行こう。Next:テストコードの書き方

[suggestrap]フォームのサジェスト機能を実装したい

$ npm install suggestrap

まず二次元の連想配列のJsonデータを作成します。
json.php
L getメソッドで”ja”を受け取ったら配列を返します

$array = array(
	array("id"=>1, "age"=>32, "name"=>"Jack"),
	array("id"=>2, "age"=>41, "name"=>"Jackie"),
	array("id"=>3, "age"=>41, "name"=>"James"),
	array("id"=>4, "age"=>20, "name"=>"Jake"),
	array("id"=>5, "age"=>28, "name"=>"Jane"),
);

$json = json_encode($array);

$query = $_GET['query'];
if(strpos($query,'ja') !== false){
	print $json;
}

index.html
L inputの入力値をqueryとしてgetメソッドで渡します。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<input id="target" type="text">
	<script src="/node_modules/suggestrap/lib/suggestrap.js"></script>
	<script>
		var req = {
			target: "target",
			url: "http://192.168.33.10:8000/json.php?query=%QUERY",
			key: "name"
		};
		var option = {
			minlength: 2,
			wildcard: "%QUERY",
			delay: 400,
			count: 5,
			id: "suggestrap"
		};
		var suggestrap = new Suggestrap(req, option);
	</script>
</body>
</html>

あああ、なるほど、検索のサジェストは、入力したqueryをajaxで渡して、それをDBからひっぱてきて表示してるのね。
仕組みがわかった。完全に理解した。なるほどねー。
もっと凄い技術使ってるのかと思ったら、普通の仕組みだ。

さて、フォントやるかー。

[progressStep.js] プログレスバーを綺麗に表示したい

progressStep.jsというのがあるので、これを使って実装したい

Github: progressStep.js

$ npm install progressbar.js

<!DOCTYPE html>
<html lang="en">
<head>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		.hoge {
			width: 400px;
  			text-align: center;
  			margin: auto;
		}
		#progressBar {
			
		}
	</style>
</head>
<body>
	<div class="hoge">
		<div id="progressBar"></div>
	</div>
	<script
  src="https://code.jquery.com/jquery-3.5.1.js"
  integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
  crossorigin="anonymous"></script>
	<script src="https://cdn.tutorialjinni.com/progressStep/1.0.3/progressStep.js"></script>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"> </script>
	<script>
		var $progressDiv = $("#progressBar");  
		var $progressBar = $progressDiv.progressStep({activeColor:"blue"});
		$progressBar.addStep("入力");  
		$progressBar.addStep("確認");  
		$progressBar.addStep("完了");  
		$progressBar.refreshLayout();  
		$progressBar.setCurrentStep(1);  
	</script>
</body>
</html>

お、ええやん、これはガチで使えそう^^

[pickr] color pickerを実装したい

RGBを入力するのは、RGBを調べるという手間が入るので、color pickerを実装したい。
pickrというライブラリがある様なので、それを使う。

$ npm install @simonwep/pickr

githubそのままですが、

<!DOCTYPE html>
<html lang="en">
<head>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<meta charset="UTF-8">
	<title>Document</title>
	<link href="/node_modules/@simonwep/pickr/dist/themes/classic.min.css" rel="stylesheet">
	<link href="/node_modules/@simonwep/pickr/dist/themes/monolith.min.css" rel="stylesheet">
	<link href="/node_modules/@simonwep/pickr/dist/themes/nano.min.css" rel="stylesheet">

	<script src="/node_modules/@simonwep/pickr/dist/pickr.min.js"></script>
	<script src="/node_modules/@simonwep/pickr/dist/pickr.es5.min.js"></script>
</head>
<body>
	<div class="color-picker"></div>
	<script>
		const pickr = Pickr.create({
		    el: '.color-picker',
		    theme: 'classic', 

		    swatches: [
		        'rgba(244, 67, 54, 1)',
		        'rgba(233, 30, 99, 0.95)',
		        'rgba(156, 39, 176, 0.9)',
		        'rgba(103, 58, 183, 0.85)',
		        'rgba(63, 81, 181, 0.8)',
		        'rgba(33, 150, 243, 0.75)',
		        'rgba(3, 169, 244, 0.7)',
		        'rgba(0, 188, 212, 0.7)',
		        'rgba(0, 150, 136, 0.75)',
		        'rgba(76, 175, 80, 0.8)',
		        'rgba(139, 195, 74, 0.85)',
		        'rgba(205, 220, 57, 0.9)',
		        'rgba(255, 235, 59, 0.95)',
		        'rgba(255, 193, 7, 1)'
		    ],

		    components: {

		        // Main components
		        preview: true,
		        opacity: true,
		        hue: true,

		        // Input / output Options
		        interaction: {
		            hex: true,
		            rgba: true,
		            hsla: true,
		            hsva: true,
		            cmyk: true,
		            input: true,
		            clear: true,
		            save: true
		        }
		    }
		});
	</script>
</body>
</html>

これは凄い。使いたいな。

[three-dots] spinnerを実装してみる

Github: https://github.com/nzbin/three-dots

$ npm install three-dots –save

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<link href="/node_modules/three-dots/dist/three-dots.css" rel="stylesheet">
	<style>
		.spinner {
			margin: 50px;
		}
	</style>
</head>
<body>
	<div class="spinner">
		<div class="dot-elastic"></div>
	</div>
</body>
</html>

なるほど、CSSで表現できるのね。処理に時間がかかる時に使えそうですな。