OmniAICreator/Qiita-1.07M huggingface dataset:
【超初心者】AWS CLIセットアップまで

微妙にわかりづらかったので書きました。
[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)が間違いないのは間違いありません。

# CLIをインストールする
↑の公式ドキュメントでまずCLIをインストールしてください。
`$ aws --version`でインストールができているか確認できます。
ここではつまらなかったので説明省きます。

## 準備
設定したい[IAMユーザーは事前に作成](https://qiita.com/iwajin/items/2cb0886aba80fddafee8)してください。
①IAMコンソール、左ペインの`ユーザー`を押下
②設定したいユーザーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/23acb16e-80a9-1c17-4744-eb9c65af59cb.png)
***
`認証情報`タブの`アクセスキーの作成`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/7a490709-17f6-92e0-3c94-ac5ff87ffdee.png)
***
`.csvファイルのダウンロード`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/302ffd15-4136-fb6e-e893-1a0fae1c0857.png)
ローカルで`[IAMユーザー]_accessKeys.csv`を開く。
`アクセスキー` `シークレットアクセスキー`を控えておく ※他人に公開しないように
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/36049bf1-47d2-c810-ff42-7083278a81c7.png)



# セットアップ
```
$ aws configure
AWS Access Key ID [None]: ”アクセスキー”
AWS Secret Access Key [None]: "シークレットアクセスキー"
Default region name [None]: ap-northeast-1
Default output format [None]: text
```
１行目の入力後、対話的に入力ができます。
２行目：控えておいた`アクセスキー`をコピペ
３行目：控えておいた`シークレットアクセスキー`をコピペ
４行目：リージョン名を指定。東京は`ap-northeast-1`
５行目：出力形式を指定。`text`の他に`json` `yaml`等、デフォルトでは`json`
&ensp;

入力内容を確認
```
$ cat ~/.aws/credentials
[default]
aws_access_key_id = *********************
aws_secret_access_key = *************************************

$ cat ~/.aws/config
[default]
region = ap-northeast-1
output = text
```

&ensp;

##　後書き
マークダウンの練習です。
Next.js（React）でページ毎にレイアウトを切り替える方法

本記事では、Next.js（React）でページ毎にレイアウトを切り替える方法を解説しています。（※TypeScriptで解説しています）

- 特定のページにはフッター無し
- LPページだけ違ったレイアウトにする

上記のようなページ毎にレイアウトを変えたい場合に有効です。

## _app.tsxで設定する
まずは`_app.tsx`で設定していきます。

```typescript:_app.tsx
import type { AppProps } from 'next/app'
import { NextPage } from 'next'
import { ReactElement, ReactNode } from 'react'

export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: (page: ReactElement) => ReactNode
}

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout
}

export default function App({ Component, pageProps }: AppPropsWithLayout) {
   const getLayout = Component.getLayout ?? ((page) => page)
   return getLayout(<Component {...pageProps} />)
}
```

## レイアウト用のコンポーネントを作成する
続いてレイアウト用のコンポーネントを作成していきます。

```tsx:Layout.tsx
import { ReactNode } from 'react'
import Header from './Header'
import Footer from './Footer'

type Props = {
  children: ReactNode
}

const Layout = ({ children }: Props) => {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  )
}

export default Layout
```

## ページ毎に使用したいレイアウトを設定する

```tsx:index.tsx
import { ReactElement } from 'react'
import Layout from '../components/layout/Layout'

const Home = () => {
  return (
    <>
      <div>ページの内容</div>
    </>
  )
}

Home.getLayout = function getLayout(page: ReactElement) {
  return <Layout>{page}</Layout>
}

export default Home
```

ページの`getLayout`に使用したいレイアウトを返すことで設定できます。
ページ毎に使用したいレイアウトを切り替えたい場合には、下記のように使用するレイアウト用のコンポーネントを変更します。

```tsx
import TopLayout from '../components/layout/TopLayout'

Home.getLayout = function getLayout(page: ReactElement) {
  return <TopLayout>{page}</TopLayout>
}
```

## 最後に

今回はNext.jsでページごとにレイアウトを切り替える方法についてまとめました。
LPページだけ違ったレイアウトにすることも可能になるので、使い道はあるかなと思います。
'React' must be in scope when using JSX  react/react-in-jsx-scope と怒られた時の対応事情

# 時間がない人用

```js:.eslintrc.cjs
  extends: ['plugin:react/jsx-runtime'],
```

# 以前の情報

React は 17 以降に **the new JSX transform** というものが存在する。

https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html

ところが、この時に `eslint` からひたすら怒られた事はないだろうか。

```console
error  'React' must be in scope when using JSX  react/react-in-jsx-scope
```

この対策、従来だと `eslint` の設定をいじるものが多かった。
いじるのは以下の二つ。

https://dev.to/chandelieraxel/why-do-react-need-to-be-in-scope-for-jsx-3hen

```js:.eslintrc.cjs
 'rules': {
    'react/jsx-uses-react': 'off',
    'react/react-in-jsx-scope': 'off'
}
```

# 今の `eslint-plugin-react`

これは最近の `eslint-plugin-react` で修正が加えられている。

https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md

> If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), you should disable this rule by extending [`react/jsx-runtime`](https://github.com/jsx-eslint/eslint-plugin-react/blob/8cf47a8ac2242ee00ea36eac4b6ae51956ba4411/index.js#L165-L179) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`).

なので、お手元の `eslintrc` に `extends` を一行追加することで対応できる。

```js:.eslintrc.cjs
  extends: ['plugin:react/jsx-runtime'],
```
STUDIOハンズオンセミナー@金沢に参加しました

# STUDIOハンズオンセミナー
こちらのイベントに参加しました。

https://connpass.com/event/266210/

# 実際に作ったサイト
約２時間ぐらいで作ったサイトです。
PCとスマホとそれぞれで開いてみてもらえると、レスポンシブルになっているのが分かると思います。

https://221118-studio-hans-on-kanazawa-yukima77.studio.site/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21408/e4a7c36a-8ee4-e081-8f47-e3bfc84214d8.png)

# ハンズオンで使用したツール
* STUDIO

https://studio.design/ja




# 大まかな流れ
1. アカウントを作ってない人はアカウント作成
1. 空白のプロジェクトからのスタート
1. BOXを使ったレイアウトのやり方
1. BOXを使って画像を入れてみる
1. TEXTを使って、それっぽい文章を入れてみる
1. マージンやバディングなどを使って、少し見やすくする方法など
1. PC版以外にタブレットやモバイル用の画面も確認（基本的に勝手にやってくれてる）
1. SNSのアイコンも追加
1. リアルタイムプレビュー機能をやってみる
1. 実際に公開までしてみる

これを比較的ゆっくり目にやりながらの２時間でした。あとは、リアル会場で参加したのですが、ネットワーク不調などもあり、そういった意味でも結構余裕のある２時間でした。

# 感想
以前に少しだけ触り方を教えてもらっていて（約１時間ぐらい）、それからテンプレートベースでイベント告知用のLPサイトを自分で作ってみたりしてみてた（それも約３時間ぐらい）状態からのスタートでした。なので、大まかな使い方などはそれなりに分かってるつもりで、ハンズオン自体は大きく困ることなくサクサクできた感じです。ただ、やっぱりなんとなく使ってた部分も多かったので（まぁ、数時間ぐらいしかやってないから偉そうなことは言えないですが）、ちゃんと説明されながらハンズオンできたので、この機能はやっぱりこういうことだよねというところもあれば、あっ、そうやって使うんだという機能もあり、かなり充実したハンズオンでした。
イベント自体はハイブリッド方式だったのですが、ちょっとリアル会場側のネットワークが不良だったのもあり、バタバタもしてましたが、充実したハンズオンだったと思います。
やっぱりこういったのは、一旦、触ってみる。そして、分かってる人と一緒にちょっとだけでもやってみるというのは、スタートする上でのハードルがめちゃくちゃ下がると思いますね(笑) ハンズオンセミナーに感謝です。

# 気づいたこと
* ブラウザは、基本的にchromeを使うこと
* マージンとパディングの使い分けは、作成や修正の手間が少ないのが基本だけど、迷ったらパディングをまずは基本で良いみたい
NotionでZoomのID・Password・招待リンクを曜日別に表示するビューを作成した

## はじめに
学校では週に3日オンラインの授業があります。
授業でもZoomを使って共有するなんてのはざらです。

最近、ZoomのID・Passwordが毎回同じであればZoom内で招待リンクを取得して踏めば1ポチでZoomに参加できることを知りました（遅い。3年かかった)

IDコピペ・Passwordコピペはもう嫌だ！
何ならもっと便利に管理したい！
というわけです。

## Notionのtemplate
早速ですが、NotionのTemplateを公開します
複製して使用して問題ありません

https://protective-icon-1bc.notion.site/33f976dad2da4a47a950a5a16ef3b66b?v=74416ecab47145a7a9ec935e123c560a

## 概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402118/74dbaa49-2b36-e8c7-f691-1e873a79e9b6.png)
中身はそんなに複雑ではありません。
ビューで「今日の曜日」の情報だけが出るようにしてあります。
ここはちょっとめんどくさかった。

## 使い方
ビューをここで追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402118/ac27b4e0-ef9b-fb44-2d84-973a9bd38039.png)

＋新規ボタンを押してZoomID,Password,URL,そのZoomが行われる曜日を指定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402118/82562e0f-ffbf-ac70-983e-4dba142b8e2b.png)

一通りZoom情報を入れ終えたら、「今日の曜日」のビューをZoomが始まる度に開くだけです。
## フィルターとプロパティの中身
フィルター自体はシンプル！チェックボックス一つだけ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402118/5c5611ec-3b6e-2903-4c75-67907ec6102f.png)

### プロパティ:曜日が今日と一致しているか？
非表示になってはいますが、
`曜日が今日と一致しているか？`
が存在します。こちらは関数のプロパティです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402118/605efd6d-58e5-b125-f996-144e0fcf2878.png)


### 関数を詳しく見る
```
if(prop("曜日指定") == formatDate(now(), "dd"), true, false)
```
(ご指摘をいただき、簡潔にすることが出来ました)

## 終わり

今までは、
```
Zoomを開いて、ZoomIDやPasswordが書かれたPDFを探して、そこからコピーして貼り付ける
```
という作業だったのが
```
Notionを開いてURLを押すだけ
```
になりました！
デプロイ後の運用

### デプロイ後の流れ
デプロイ後に開発環境で行なった変更を、デプロイしたアプリケーションに取り込む方法がいつもわからなくなるため、メモ代わりにまとめました。

#### ❶EC2へSSHでログインする
```
username:~/environment $ ssh -i ~/.ssh/practice-aws.pem ec2-user@xx.xx.xx.xx
```
:::note info
@xx.xx.xx.xxはEC2のパブリックIPアドレス
:::

#### ❷アプリケーションへ移動
```
[ec2-user@ip-xx-xx-xx-xx ~]$ cd アプリケーション名
```
#### ❸　GitHubからpull
最新のコードを取り込むためにGitHubからpullします。
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$git pull origin main
```


#### ❹変更したフォルダーによる運用方法
Gemfileを変更した場合
---------------------------
１. ローカルからリモートリポジトリへpush
２. SSHでEC2へ接続
３. EC2上でアプリケーションへ移動
４. git pullする
５. 以下コマンドを実行
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ bundle install --path vendor/bundle --without test development
```
CSS/JavaScript/画像を変更した場合
-------------------------------------
１. ローカルからリモートリポジトリへpush
２. SSHでEC2へ接続
３. EC2上でアプリケーションへ移動
４. git pullする
５. プリコンパイルを行う
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ bundle exec rails assets:precompile RAILS_ENV=production
```
マイグレーションファイルを変更した場合
------------------------------------
１. ローカルからリモートリポジトリへpush
２. SSHでEC2へ接続
３. EC2上でアプリケーションへ移動
４. git pullする
５. マイグレーションを行う
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ bundle exec rails db:migrate RAILS_ENV=production
```
#### ❺アプリケーションサーバー（Puma）を起動
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ rails s -e production
```

#### アプリケーションサーバー（Puma）を停止するとき
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ kill $(cat tmp/pids/puma.pid)
```

#### 本番環境でデータベースをリセットしたいとき
```
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rails db:drop
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ rails db:create RAILS_ENV=production
[ec2-user@ip-xx-xx-xx-xx アプリケーション名]$ rails db:migrate RAILS_ENV=production
```
【未解決】Helmチャートでインストールされるリソースの順番を変えたい

## Helmチャートによるリソースのインストール順について

以下のソースで定義されている。

https://github.com/helm/helm/blob/main/pkg/releaseutil/kind_sorter.go#L31

現時点のソースを抜粋。標準だとこの順番でインストールされる。
```go
// Those occurring earlier in the list get installed before those occurring later in the list.
var InstallOrder KindSortOrder = []string{
	"Namespace",
	"NetworkPolicy",
	"ResourceQuota",
	"LimitRange",
	"PodSecurityPolicy",
	"PodDisruptionBudget",
	"ServiceAccount",
	"Secret",
	"SecretList",
	"ConfigMap",
	"StorageClass",
	"PersistentVolume",
	"PersistentVolumeClaim",
	"CustomResourceDefinition",
	"ClusterRole",
	"ClusterRoleList",
	"ClusterRoleBinding",
	"ClusterRoleBindingList",
	"Role",
	"RoleList",
	"RoleBinding",
	"RoleBindingList",
	"Service",
	"DaemonSet",
	"Pod",
	"ReplicationController",
	"ReplicaSet",
	"Deployment",
	"HorizontalPodAutoscaler",
	"StatefulSet",
	"Job",
	"CronJob",
	"IngressClass",
	"Ingress",
	"APIService",
}
```

## 課題

上記の``InstallOrder``にインストール順を縛られると困るケースが、例えば以下のようにある。

* 特定の``Job``だけ先に（後に）実行したい。
* ``InstallOrder``に未登録のリソースのインストール順を制御できない。例えば``CustomA``と``CustomB``のカスタムリソースがあり、「``CustomA``は``CustomB``よりも後にインストールさせたい」場合に、``CustomA``が先にインストールされてしまう。

筆者が具体的に困ったのが、Argo Workflowsのカスタムリソースで``WorkflowTemplate``のリソースで定義したテンプレートを``Workflow``から呼ぼうとした時に、先に``Workflow``のリソースがインストールされてエラーになってしまったこと。
何度か``helm install``を試してみたが、エラーは起きたり起きなかったりするので、[InstallOrder](https://github.com/helm/helm/blob/main/pkg/releaseutil/kind_sorter.go#L31)に登録されていないカスタムリソースのインストール順は気まぐれに変わっていると思われる。

## 現状の解決策

インストール順を変えたいリソースのマニフェストで、下例のように``metadata.annotations``に``helm.sh/hook``のキーと値を追加すると**一応は**解決する。

```yaml
metadata:
  annotations:
    "helm.sh/hook": pre-install, pre-upgrade
    "helm.sh/hook-weight": "-5"                  # 必要に応じて設定
    "helm.sh/hook-delete-policy": hook-succeeded # 必要に応じて設定
```

例えば``helm.sh/hook``に``pre-install``や``pre-upgrade``を設定すると、先にそのリソースがインストールされる。``post-install``, ``post-upgrade``だと後でインストールされる。

各アノテーションの具体的な使い方については、以下の公式ドキュメントを参照いただきたい。

https://helm.sh/docs/topics/charts_hooks/

hooksの挙動については、[Release lifecycle management with Helm](https://craftech.io/blog/release-lifecycle-management-with-helm/)に書かれた以下の図を見ると、筆者も何となく理解できた。
<img src="https://craftech.io/blog/wp-content/uploads/2021/08/Helm-Blog2.png">
だが図を見てみると、``helm.sh/hook``のアノテーションはあくまで「本体リソースをインストールするための前処理／後処理」としてリソースを動かす場合を意図したもののようので、本体（図でいうv1.0、v1.1の箱）に持ってきたいリソースは結局のところ、[InstallOrder](https://github.com/helm/helm/blob/main/pkg/releaseutil/kind_sorter.go#L31)の束縛からは逃れられない…。

※実際、``helm uninstall``でリソースを消そうとしたところ、上図のv1.0、v1.1に相当するリソースは消えるのだが、``helm.sh/hook``のアノテーションをつけたリソースは仲間外れにされて消えてくれなかった。

なので現状、この課題の根本的な解決策は見つかっていないと認識している。

以下のGitHubのissueでも「``helm.sh/order-weight``のようなアノテーションがあるといいのに」という記載があるので、おそらく未解決なのだろう。

https://github.com/helm/helm/issues/8439

※ここまで読んでいただいた方に解決策をご提示できずに申し訳ないですが、解決法がわかり次第本記事をアップデートさせていただきます。
【Docker】mount=type=cacheの使い方【Rails】

## Dockerfile

Rails環境用のDockerfileで`$GEM_HOME`に`--mount=type=cache`を設定するには以下のようにします。

```Dockerfile
...

WORKDIR /home/${USER_NAME}/${PROJECT_NAME}
COPY --chown=${USER_NAME} Gemfile* /home/${USER_NAME}/${PROJECT_NAME}/
RUN --mount=type=cache,uid=1000,target=/home/${USER_NAME}/.cache/bundle <<-EOF
  set -e
  GEM_HOME=/home/${USER_NAME}/.cache/bundle bundle install
  cp -aRT /home/${USER_NAME}/.cache/bundle ${GEM_HOME}
EOF

...

```

一度`~/.cache/bundle`にインストールしてから`$GEM_HOME`にコピーします。

* `GEM_HOME=/home/${USER_NAME}/.cache/bundle bundle install`  
  `GEM_HOME`を一時的に変更して`bundle install`。  

* `cp -aRT /home/${USER_NAME}/.cache/bundle ${GEM_HOME}`  
  `-a`はサブディレクトリや属性なども含め、可能な限りすべてを保持しながらコピーする。
  `-R`はコピー元にディレクトリを指定した場合、再帰的に（サブディレクトリも含めて）コピーする。
  `-T`はコピー先（最後の引数）がディレクトリでも特別扱いしない。
WindowsのExplorerを開いているフォルダーでWindows Terminalを起動する

## TL;DR

WindowsのExplorerを開いているフォルダーでコマンドを叩きたいとき、Windows Terminalをそのフォルダーで起動する簡単な方法を見つけたので紹介するよ。

## 背景

むかし、インフラエンジニア界隈の友人に「Explorerのアドレスバーにcmdって入力するとそのフォルダーでコマンドプロンプトが開くよ」って教えてもらってもらった。
あまりに便利なのでずっと使っていたのだけれど（pwsh.exeでもできた）、最近Windows Terminalを使うようになってからこれができないことが判明、ちょっと試行錯誤したらできたので共有する、というもの。

## 期待する動作

※PowerShell Core(pwsh.exe)がインストールされている前提での再現です。

1. Explorerのアドレスバーに`pwsh`と入れてエンター
1. pwshがそのフォルダーで開く (Good)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/61fbd7b0-7809-f6c9-bf3c-a46acd76e70e.png)



## Windows Terminalでの、実際の動作

※Windows Terminalがインストールされている前提での再現です。

1. Explorerのアドレスバーに`wt`と入れてエンター
1. Windows Terminalが別のフォルダーで開く (Better to fix)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/ec413ef3-9333-1bc0-449e-8b1f701fd9cb.png)

## 対策

詳細は後述することとして、以下の通りにすると期待した動作になる。

### 設定を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/7e880ead-eb19-35dc-45eb-f7a8a611fd40.png)

### 設定を変える

「既定値」> 「開始ディレクトリ」を`.`にして、保存する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/010a9294-ac1f-bae1-6325-22bffb3aa8cc.png)

### ためす

`wt`と打ってEnter

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/e6af2d23-664a-ca63-1675-59996ed8de21.png)

できた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/ac21064c-57ef-c21e-9d07-ccd7ca536109.png)


## なんでこれでいいのか？

よくわからないけど、[Windows Terminalのドキュメント](https://learn.microsoft.com/en-us/windows/terminal/command-line-arguments?tabs=windows#target-a-directory)に`-d`オプションが紹介されていることと、Windows Terminalの[デフォルト設定に`%USERPROFILE%`が既定値だとあること](https://learn.microsoft.com/ja-jp/windows/terminal/customize-settings/profile-general#starting-directory)との情報があった。
それで、この設定変えてみようと思ったら`%USERPROFILE%`ってフィルインされてたので、多分この設定値は`-d`の引数なんだろうなーと思い、試したら期待した動作となりました、という次第です。

## 参考URL

- Using command line arguments for Windows Terminal
    - https://learn.microsoft.com/en-us/windows/terminal/command-line-arguments
- Windowsターミナルでの全般的なプロファイル設定
    - https://learn.microsoft.com/ja-jp/windows/terminal/customize-settings/profile-general
Selenium コードを GUI で自動生成して実行するアプリを作りました

## 動機
現場ではまだまだ手動でのテストが多いと聞き、手動でのテストをしている人向けに自動テストに慣れてもらいたいと思い、自動テストコードを GUI で生成して、それを AWS上で実行できるアプリを作りました。
巷で売られている自動化ツールの簡易版みたいなもんです（Webページの画像から Xpath などを指定できない、とか）。

## 成果物

公開している URL は、

~~https://master.d28diowzfkuhqr.amplifyapp.com~~

になりますが、現在は使えません（サーバー代節約のため）。

公開しているコードは、

https://github.com/YmBIgo/auto-run-test-code

にあります。

#### GUI について

GUI で操作とは言っても、Xpath や If文・While文 くらいの基本的な IT知識は必要になります。
基本的な GUI は下のようになっています。

![スクリーンショット 2022-11-19 18.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92647/afda04e1-fd43-4ece-c5f5-e89e1fb64047.png)

![スクリーンショット 2022-11-19 19.34.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92647/e47ddad9-7d45-a2c9-4754-8f3254608042.png)

右側のパネル で サイト名入力・命令の入力・テスト結果の表示・左側のパネルで 命令を入力します。
命令は、「変数作成・If文・While文・変数代入・クリック・文字入力・結果チェック」の７種類あります。
それぞれを説明すると、

###### 1. 変数作成
  後の「変数代入」「結果チェック」「文字入力」で使う変数を定義します。
###### 2. If文
  条件に合っていた場合は、If文内で定義した「変数代入」「クリック」「文字入力」を実行します。条件式では、特定の文字列が上記の変数と「同じ」か「違う」か「含まれる」かを判定します。
###### 3. While文
  特定の「変数代入」「クリック」「文字入力」を定義し、それを何回か実行できるようにします。
###### 4. 変数代入
  現在のページから、Xpath を取得して その内容を変数に代入します。Xpath が取得されなかった場合は、空の文字列を代入します。
###### 5. クリック
  現在のページから、Xpath を取得して その要素をクリックします。要素が存在しない場合は、次以降の命令はスキップされ、全体でエラーが返ってきます。また、クリック後は DOM の描画があるので 2秒待つようにしています。
###### 6. 文字入力
  現在のページから、Xpath を取得して その要素に変数か値を送ります。入力欄に入力する時などに使います。
###### 7. 結果チェック
  ある変数が、特定の文字列と「同じ」か「違う」か「含まれている」かを判定します。この判定の結果は、API のレスポンスに入ります。結果チェックは、全体のフローを通して１回しか呼び出せません。

のようになっています。
これらの命令を組み合わせて、Selenium によるスクレイピングを行って行きます。
これらのフロントエンドは、React で作られています。Redux などは使わず Hooks で状態管理しています。

#### API バックエンド

この GUI の情報は、JSON で AWS lambda に流れて、AWS lambda 内で python の selenium コードに変換され、実行されます。lambda内では最低限のセキュリティは施されていますが、変数定義の時に予約語や数字を入力された場合に、それを変更する機能などはないため、予約語や数字を入力するとエラーが返ってきます。

もし手短に自分の環境で試したい場合は、flask で作れる環境もあるので、そちらを試してみて下さい（APIコールの URL を localhost:5000にする必要はありますが）。lambda 内のセキュリティは flask より少しだけ強くしていますが、まだ弱いかもしれません。

https://github.com/YmBIgo/auto-run-test-code/tree/master/test_automation_flask

---

lambda では、CORS で OPTION を簡単に作れる API GateWay の HTTPAPI を使用してエンドポイントを作っていて、データは S3 に保存されています。

#### JSONによる保存・ロード、CSV保存

JSON でテストケースを保存・ロードしたり、テスト結果を CSV で保存できたりする機能もあります。

## 今後について

一通り機能が出来たので、公開してみたが、デザインも微妙だし、欲しい機能などもあったら教えて下さい。

あまり関係ありませんが、作っている時にちょうど [テスト自動化のプロジェクト](https://qiita.com/dyamada_/items/1c85bc754e67ecdfff31) を見つけたが、みんな考えていることは同じだなと思いました。
【Rails】undefined method `posts_path' for #<ActionView::Base:0x00000000011878>

# 状況
以下のようにresourcesメソッドを使って、usersの中にpostsをネストするようなルーティングを書いた。
```ruby:config/routes
Rails.application.routes.draw do
  root 'home#show'
  resources :users, only: [:show] do
    resources :posts, only: [:index, :new, :create, :destroy]
  end
end
```
postsコントローラーは以下のように書いた。
```ruby:controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :authenticate_user!, only: [:new, :create, :destroy]

  def index
    @user = User.find(params[:user_id])
    @posts = @user.posts
  end

  def new
    @post = Post.new
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      redirect_to user_posts_path
    else
      render action: :new
    end
  end

  def destroy
  end

  private

  def post_params
    params.require(:post).permit(:title, :content)
  end
end
```



また、postの新規作成用のviewは以下のコードを書いた。
```erb:posts/new.html.erb
NEW Posts
<%= form_with(model: @post, local: true) do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :content, placeholder: "Compose new post..." %>
  <%= f.submit "Post" %>
<% end %>
```

その結果、postの新規作成画面に遷移した際に以下のようなエラーが表示された。
```
NoMethodError in Posts#new
undefined method `posts_path' for #<ActionView::Base:0x00000000011878>
```
# 対処法
viewのform_withについて以下のように```url: user_posts_path```とパスを追記する。
```erb:posts/new.html.erb
NEW Posts
<!-- url: user_posts_pathを追記↓ ---!>
<%= form_with(model: Post.new, url: user_posts_path, local: true) do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :content, placeholder: "Compose new post..." %>
  <%= f.submit "Post" %>
<% end %>
```
# 原因
railsのformメソッドはデータを送信（POSTリクエスト）しデータを新規作成する際に、送信する先のパス（URL）が指定されていなければ、よきにはからってくれる。
すなわち今回のケースでは```@post```というモデルが指定されているため、Railsは ```posts_path```というURLを照会しようと試みた。
しかし、冒頭で定義しているように、postsリソースへのルーティングはusersリソースへのルーティングにネストされている。
従って、postsリソースへのURLは```posts_path```ではなく、```user_posts_path```となっているので、これを指定しなくてはならない。
（このあたりの確認については localhost/rails/infoにアクセスするとルーティングの一覧を取得できる。)
ESP32: 加速度センサーの値を読む

こちらのページを参考にしました。
[ESP32で加速度センサの値に応じてモータ制御](https://qiita.com/Voltric01i/items/77dd63472820ab12c6dd)

プログラム

```text:get_accel.ino
// ---------------------------------------------------------------------
//	get_accel.ino
//
//					Nov/19/2022
// ---------------------------------------------------------------------
#include <Wire.h>
#include <Arduino.h>

// デバイスアドレス(スレーブ)
uint8_t DEVICE_ADDRESS = 0x53;  

// XYZレジスタ用のテーブル(6byte)
uint8_t RegTbl[6];  

void getAccelerationData();

/* 使うピンの定義 */
const int IN1 = 25;
const int IN2 = 26;

/* チャンネルの定義 */
const int CHANNEL_0 = 0;
const int CHANNEL_1 = 1;

// ---------------------------------------------------------------------
void setup() {
	Serial.begin(115200); 

	Serial.println("*** setup start ***");

	// マスタとしてI2Cバスに接続する
	Wire.begin();			 
	// DATA_FORMAT(データ形式の制御) 
	Wire.beginTransmission(DEVICE_ADDRESS);	
		// DATA_FORMATのアドレス		
	Wire.write(0x31);
		// 「最大分解能モード」 及び 「±16g」 (0x0B == 1011)
	Wire.write(0x0B);	
		// 「10bit固定分解能モード」 及び　「±16g」にする場合 (0x03 == 0011)
		// Wire.write(0x03);
	Wire.endTransmission();

	Serial.println("*** setup ddd ***");
}

// ---------------------------------------------------------------------
void loop() {
//	Serial.println("*** loop ***");

	getAccelerationData();

	// データを各XYZの値に変換する(LSB単位)
	int16_t x = (((int16_t)RegTbl[1]) << 8) | RegTbl[0];
	int16_t y = (((int16_t)RegTbl[3]) << 8) | RegTbl[2];
	int16_t z = (((int16_t)RegTbl[5]) << 8) | RegTbl[4];	


	// 各XYZ軸の加速度(m/s^2)を出力する
	Serial.print("X : ");
	Serial.print( x * 0.0392266 );
	Serial.print(" Y : ");
	Serial.print( y * 0.0392266 );
	Serial.print(" Z : ");
	Serial.print( z * 0.0392266 );
	Serial.println(" m/s^2");

	delay(3000);
}

// ---------------------------------------------------------------------
//加速度データ取得
void getAccelerationData(){
	// XYZの先頭アドレスに移動する
	Wire.beginTransmission(DEVICE_ADDRESS);
		Wire.write(0x32);
	Wire.endTransmission();

	// デバイスへ6byteのレジスタデータを要求する
	Wire.requestFrom(DEVICE_ADDRESS, 6);

	// 6byteのデータを取得する
	int i;
	for (i=0; i< 6; i++){
		while (Wire.available() == 0 ){}
		RegTbl[i] = Wire.read();
	}

}

// ---------------------------------------------------------------------
```
Firestore でerror 

### エラー内容
```
Listen for query at todos failed: Missing or insufficient permissions.
```

### 解決方法

ルールを変更する。ただ、セキュリティー的に良くないから、本番の時は、認証をした方がいいらしい。また後で調べる。


参考URL:
https://stackoverflow.com/questions/46590155/firestore-permission-denied-missing-or-insufficient-permissions

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      // ここのif falseをif trueにする
      allow read, write: if false;
    }
  }
}
```

![Screen Shot 2022-11-19 at 18.00.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537802/e51fe129-673e-c5d7-505f-3e66110ee084.png)


![Screen Shot 2022-11-19 at 18.01.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537802/f19e536e-1160-5906-97a0-1170e92f0592.png)

とりあえず、メモ書き
APIについてまとめてみた

# APIについて

APIはApplication Programming Interface（アプリケーションをプログラミングするためのインターフェース）の略

> **あるソフトウェアやプログラムが持つ機能や情報を、別のプログラム上でも利用できるように繋ぐ仕組みです。**ここでのインターフェースとは、「つなぐもの」という意味です。
> 

## ****API連携の仕組みを****レストランに例えると

客がレストランに入り、スタッフに料理を注文します。スタッフはその注文をシェフに伝えます。シェフは料理を作り、スタッフが客のところに届けます。

この例において、客に相当するのがAPIの利用者、スタッフがAPI、そしてシェフに相当するのがAPI提供元のサーバーです。APIに注文（リクエスト）することで、サーバーから出されたデータや情報が、APIを通じて利用者に届けられます（レスポンス）。

[【初心者向け】APIとは？概要や活用メリット・使い方を解説](https://blog.hubspot.jp/api)

[APIを探して、試して、使える【APIBank】](https://www.apibank.jp/ApiBank/main)

## 自分が使う予定のyoutubeAPIで例えると

APIはYouTubeなどの企業が自社のデータを使わせてくれるサービス。流れとしては、APIを使いたいサービスからAPIリクエストを送り、YouTubeがこのリクエストに対してAPIレスポンス(YouTubeのデータ)を返すという流れ。
step間/job間で値の共有【GitHubActions】

# やりたいこと
GithubActionsワークフローの、step間や、job間で、前に定義した値を次step/jobで使うように共有したい。

# やりかた
## step間の値の共有
- `$GITHUB_ENV`を使用する。

```yaml
jobs:
    sample-job:
        runs-on: ubuntu-latest
        steps:
            - name: Set value
              run: echo "HOGE=hoge" >> $GITHUB_ENV
            
            - name: Use value
              run: echo "HOGE: ${{ env.HOGE }}"   
              # >> HOGE: hoge     
```

## job間の値の共有
- step間での共有は`$GITHUB_ENV`でできていたが、jobが異なると`$GITHUB_ENV`は使えない。
- 2022年10月リリースの`$GITHUB_OUTPUT`を使用する。
  - 今までは`set-output`が使用されていたが、こちらは2023年５月31日をもって完全に使用できなくなるとのこと。
  - [公式ブログ](https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/)

```yaml
jobs:
    job1:
        runs-on: ubuntu-latest
        outputs:
            hoge: ${{ steps.set_outputs.outputs.hoge }}
            fuga: ${{ steps.set_outputs.outputs.fuga }}
        steps:
            - id: set_outputs
              name: Set outputs
              run: |
                echo "hoge=hoge" >> $GITHUB_OUTPUT
                echo "fuga=fuga" >> $GITHUB_OUTPUT

    job2:
        runs-on: ubuntu-latest
        needs: job1
        steps:
            - name: Use outputs
              run: |
                echo "hoge: ${{ needs.job1.outputs.hoge }}"
                echo "fuga: ${{ needs.job1.outputs.fuga }}"
```

# 参考
- [公式ブログ GitHub Actions: Deprecating save-state and set-output commands](https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/)
- [Developers IO / GitHubActionsで変数を間接参照したい](https://dev.classmethod.jp/articles/github-actions-variable-indirection-reference/)
- [公式ドキュメント　ジョブの出力の定義](https://docs.github.com/ja/actions/using-jobs/defining-outputs-for-jobs)
GASでUrlFetchAppでBasic認証で日本語ユーザー名で

## 原因

仕事でOracle B2Cというやつを召喚しまして。
したらまあ、構築してくれた人が `Account` を日本語名で作ってくれやがったりしたわけです。

それをAPIでごにょごにょするわけです。
C#で組むのでもよかったのですが、後々の保守だったりの手間を省くためにGASを使う方向で、となった時に問題になるのがアカウントの日本語名ですよ。

## Oracle B2Cの仕様

Oracle B2CさんのAPIの認証は簡単で、BASIC認証です。
ざっくり [こういう仕様](https://docs.oracle.com/en/cloud/saas/b2c-service/22c/cxsvc/c_osvc_quick_start.html) ですね。

普通のBASIC認証のようです。
`base64変換( 名前 + ':' + パスワード )` をやればいいということで。
GASで普通にやれば以下のようになりますね。

```javascript
const ORACLE_USER = "ほにゃらら";
const ORACLE_PASS = "foobar";
const ORACLE_DOMAIN = "test.example.com";

function myFunction() {
  var url = `https://${ORACLE_DOMAIN}/services/rest/connect/v1.4/incidents`;
  var authCode = Utilities.base64Encode(ORACLE_USER + ":" + ORACLE_PASS);
  var res = UrlFetchApp.fetch(url, {
    'method': 'get',
    'headers': {
      'Authorization': " Basic " + authCode,
      'osvc-crest-application-context': '1',
      "muteHttpExceptions": true
    }}
  );
}
```
試してみると、

```plaintext
Exception: Request failed for https://test.example.com returned code 401. Truncated server response: {"type":"https://test.example.com/services/rest/connect/exceptions/OSC-CREST-00014","title":"このサイトを使用する権限がありません","status":401,"detail":"You are no...
```

## JavaScriptの文字列の内部処理形式はUTF-16です

先のコードが権限異常なのは、「 [JavaScriptは文字コードとしてUnicodeを採用し、エンコード方式としてUTF-16を採用しています。](https://jsprimer.net/basic/string-unicode/) 」ということらしい。
UTF-16にbase64かけちゃうので認証コードがおかしくなるんですね。
なので、UTF-8に変換してやらなければいけない。

結局、以下のコードになりました。

```javascript
const ORACLE_USER = "ほにゃらら";
const ORACLE_PASS = "foobar";
const ORACLE_DOMAIN = "test.example.com";

function myFunction() {
  var url = `https://${ORACLE_DOMAIN}/services/rest/connect/v1.4/incidents`;
  var blob = Utilities.newBlob(ORACLE_USER + ":" + ORACLE_PASS);
  var codeSrc = blob.getBytes();
  var authCode = Utilities.base64Encode(codeSrc);
  var res = UrlFetchApp.fetch(url, {
    'method': 'get',
    'headers': {
      'Authorization': " Basic " + authCode,
      'osvc-crest-application-context': '1',
      "muteHttpExceptions": true
    }}
  );
}
```

blob作って変換してやるみたいです。
参考元は、[ここ](https://qiita.com/jsoizo/items/948e23231417d203eefa) とか [ここ](https://qiita.com/a_eau_/items/01bc14bfc5cb5ef12e64) とか。

### ちなみに

ちなみに、C#だと以下。

```csharp
var code = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{ORACLE_USER}:{ORACLE_PASS}"));
var client = new HttpClient();
client = new HttpClient() { BaseAddress = new Uri($"https://{ORACLE_DOMAIN}"), };
client.DefaultRequestHeaders.Add("osvc-crest-application-context", "1");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", code);
var res = await client.GetAsync($"/services/rest/connect/v1.4/incidents");
```

よくあるC#のBASIC認証のサンプルコードだと、 `Encoding.ASCII.GetBytes` を使ってあるけど、UTF-8を使うようにしておく、と。
【超初心者】IAMユーザーの追加

自分のAWSアカウントを持っている前提で書きます。
[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html)
&ensp;

IAMのコンソールを開く
①左ペインの`ユーザー`を押下
②`ユーザーを追加`を押下
![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/7fb5c2e3-283c-6f7f-cabd-98b63c3cedec.png)
***
追加するユーザー名を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/feb98fed-6704-cd6e-7565-41b877783c67.png)
***
①各チェックを入れる
②`次のステップ:アクセス権限`を押下　※コンソールで操作するためには２つ目のチェックが必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/c9035cda-c875-7c5c-7047-19718233c880.png)
***
`既存のポリシーを直接アタッチ`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/43f7ad41-5d4e-594f-a1e7-2b27315adf60.png)
***
①`AdministratorAccess`にチェックを入れる　※必要な権限を設定してください
②`次のステップ:タグ`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/e6333551-65b7-07d8-75c7-03de26af1b81.png)
***
`key`と`value`を何にかしら入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/7e3a5505-adc2-6bc8-5398-f202b191f89e.png)
***
入力内容を確認
`ユーザーの作成`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/1d6d9694-ae89-65f8-d596-9d76892f86d0.png)
***
ステータスが`成功`になっていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/669aa513-23b7-8379-fcb7-e1e1a8292ef4.png)
***
IAMコンソールの左ペイン`ユーザー`を見るとユーザーが追加されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779468/da782c20-26b5-8fd9-c644-8522ed3bf04b.png)

##### 後書き
マークダウンの練習です。
わからないことにぶつかった時の質問の仕方

駆け出しの人のツイートを見て気になったことがあったので書いてみました。

わからないことがあるんだけど、何から質問すればよいか、わからない。。。
これ、私も社会人1年目・2年目の時はよくありました。

こういう時って質問したいけど、
わからないこと多すぎて質問される人に負担がかかる、付き合ってもらえるだろうか、、
という思いになってるのでは？

あくまでボクの考えだが、
・自分がどういう状況や背景にあって、困っているのか
・わからないことについて、質問する前にどこまで調べたか
これを書くと、質問される側がたすけたい！
という心理になると思う。

たとえば、
ーーー
・〜について、教えてもらえませんか？
私は社会人に一年目で業務の中でいきなり実装を任されたのですが、まわりに年が近く質問しやすいひとが身近にいないので、困っています。
〜について下記サイトでしらべたのですが、
いまいちどういうことか、わからなくて。
（調べたサイト、一つでなく三つくらい）

わからないなりに自分が理解した内容をかきます。
（理解した内容を書く）

回答よろしくお願いします。

ーーー

後半に書いた、（自分が理解した内容）は
別にそのかいた内容が正しいかということはあまり重要ではないと思う。（時にはちんぷんかんぷんな文章かもしれない）

ここで大事なのは、
・自分が頑張って理解しようとしているよ、という意思表示
・質問されている人からみると、（どのレベルでわかっていないか）読み取れないため、その点を明確にするために自分が理解した内容をわからないなりにアウトプットする
ことだと思う。

参考になれば。
プロトコル、TCP/IPって何？

### この文章を読んでほしい人
- ネットワーク学習初心者（←筆者はネットワーク設計など実際の業務で大の初心者なので、ネットワークプロフェッショナルの方も修正などいつでもお待ちしてます..!!）
- 「プロトコル」という言葉を業務や自学習でよく聞くが、意味を腹落ちしきれていない人

### この文章を読めば
- 「プロトコル」という言葉の意味がざっくりと理解できる。
- TCP/IPが何かをざっくりと理解できる。

### そもそもプロトコルとは？

プロトコルとは、「コンピュータとコンピュータがネットワークを利用して通信するために決められた約束事」のこと。
例えば、ある人とある人が会話する時、「何語で話すか」がプロトコルになる。

Aさん→〇〇を「日本語」で伝える。
Bさん→〇〇を「英語」で伝える。

この「日本語」と「英語」がプロトコル（通信の約束事）。そしてプロトコルは、様々な種類のコンピュータ同士の接続の約束事として使われているのだが、コンピュータ同士の接続は階層構造になっている。そしてその各階層ごとに、「プロトコル」は接続の約束事として使われている。

### プロトコルの全体像

コンピュータとコンピュータ同士の接続には様々な種類がある。
例えば、MacパソコンとWindowsパソコンの接続。
その他には、gmail.comと〇〇.jpの接続。これらを大きく分けると以下のような階層構造になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516254/6ae3098c-3f92-e331-ccdd-c6fa4da8ae53.png)

先に挙げたMacパソコンとWindowsパソコンの接続はインターネット層で行われるし、gmail.comと〇〇.jpの接続はアプリケーション層で行われる。

### TCP/IPって何？

1つ前の例に戻ると、AさんとBさんが話すためには、共通言語で話す必要がある。
つまり、AコンピュータとBコンピュータが通信するためには、「共通のプロトコル」が必要だ。
（macとwindowsがそれぞれ独自のプロトコルを使っていては、お互いに通信ができない.. mac同士、windows同士でしか通信ができずに不便）

そこで、現在広く使われているのが、「TCP/IP」という標準化されたプロトコルだ。

※TCP/IPという言葉の中には、TCPとIPという2つのプロトコルだけではなく、IPで通信する際に必要となる多くのプロトコルが含まれていることが多い。（前述した通り、各階層ごとに必要なプロトコルが違うから、共通化されたTCP/IPプロトコルの中にも大量のプロトコルがある。

#### TCP/IPのすごいところ

1. オープンにTCP/IPの設計について議論できるところ。
→世界中誰でも参加できるメーリングリストを使って、設計について議論し期限を決めて適宜改善していっている。

2. 「実際に動くか」を何よりも重視している。
→「設計書よりもまず実装」という意識で開発している。

### 参考文献

上記に記載してあるものの100倍くらいの詳しさでわかりやすく書いてあるので初心者に大変おすすめです! 

マスタリングTCP/IP入門編


https://www.amazon.co.jp/s?k=%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0+tcp+ip+%E5%85%A5%E9%96%80+%E7%B7%A8&adgrpid=123599780051&gclid=CjwKCAiAmuKbBhA2EiwAxQnt7z25shycQH7EUISHmjXrR_AfnVzzSLeVjcYRoDe2vYD32RkJ9OmghhoCt7IQAvD_BwE&hvadid=618622583890&hvdev=c&hvlocphy=1009341&hvnetw=g&hvqmt=e&hvrand=4927596946241833843&hvtargid=kwd-417611595988&hydadcr=27271_14598094&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_9ptanjo390_e



画像お借りしました。
https://www.infraexpert.com/study/tcpip.html
SQLで関数（postgresql）

# 初めに
https://qiita.com/toshikawa/items/d93791c3f93d381dedb0

で使ったデータを色々やるために関数を作ってみたので忘備録

# 関数

```sql:華氏からセ氏
%%sql
DROP FUNCTION IF EXISTS cel_far;

CREATE OR REPLACE FUNCTION cel_far(f smallint) RETURNS integer AS $$
    BEGIN
        RETURN (($1 - 32) * 5 / 9);
    END;
$$ LANGUAGE plpgsql;
```

# ハマったところ

[CREATE FUNCTION](https://www.postgresql.jp/document/9.3/html/sql-createfunction.html)
とか見つつやってみたけど関数がないよ。のエラーばかり。

結果的に`cel_far(f smallint)`のデータ型がテーブルのデータ型と一致していないと動かないことに気づいた。 `orz`

## まとめ

```sql:
%%sql temp_plot <<
select pdt, cel_far(max_temp) as max_temp, cel_far(mean_temp) as mean_temp, cel_far(min_temp) as min_temp
from weather
where pdt between '2015-12-01' AND '2016-04-30';
```

```python:
temp_plot.set_index(temp_plot['pdt'], inplace=True)
temp_plot.plot()
```
　とか、華氏を摂氏に変えたりするといった複数の列に一緒のことをやるには、関数作ると楽ですね。
直感を信じますか？マーケットを信じますか？

![スクリーンショット 2022-11-19 17.36.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/1460ff7a-520c-de75-35e2-11d1711a7c31.png)

ファスト映画で５億円もの賠償金とのニュース！
https://news.yahoo.co.jp/pickup/6445139

皆さんは、ファスト映画どう思いますか？
勝手にネットにあげるという行為自体の著作権問題だと思います。しかし、倍速再生については、大好きです。
再生速度をあげれるものについては、必ず再生速度をあげて見ます。Youtube,TVer,etc。
通常速度だとまったりして、ダルくてダルくて。

# これって勝手なエゴだなぁと思うこと
話は変わりますが、今、川口春奈主演のsilent「ドラマ」が泣けると話題です。PCに向かいながら、Tverをヘビー視聴している僕も当然、silentを見てるのですが、silentは視聴に困ります。というのもPCで作業しながら見てるのですが、silentは、手話で字幕の時間が結構多い。字幕だと画面を凝視してない僕にとっては話が理解できなくなってしまいます。困るんですよねｗ　こーいう人もいるんだと思って欲しい。
ファスト映画を批判してる人達がいて、通常速度でちゃんと見て欲しいと。
そんなの作り手側の勝手なエゴでしかないと思う。見る側の見方を強制しないで欲しい。
裸の王様と一緒だよ。

# 周りからどう見られてるのか考えてみよう
世の中、自分のエゴを一方的に押し付けてくる人が本当に多いと思う。飲食店もそういうお店は多いし、べき論を主張していてくるステレオタイプの人も多い。
コンテンツなんか、配信したらどういう使われ方をするのかは、ユーザー次第だし、それが新しい時代を作っていくし、そこから生まれるコンテンツも存在するはず。むしろ新しい使い方を提案してくれてありがとうと言って欲しい。

# 商品とかサービスでもよくありますね。
話は古いが、ベータとVHSの競争は、これの典型例だ。ベータは、高品質で、小さく、ユーザに受け入れられるとソニーは思っていたが、ビクターのVHSは、画質は落としても録画時間を２時間とする事で広くユーザーに受け入れられた。そしてVHSが録画テープとしては、デファクトとなった。マーケット調査に失敗した事例だと思う。

# Mac vs Windowsも
PCで言えば、WindowsとMacの戦いの歴史がある。Windows95が出た時に、OSのマーケットシェアは完全にMicrosoftの物となった。理由は色々とあるだろうが、Macユーザーは、Macの方が使いやすいしwindowsはMacを真似たと言っていた。
僕の感覚では、Windowsの成功は、OSをどのハードウエアでも動かすことが出来る様にオープンにした事だと思う。これにより沢山のハードメーカーがWindows95対応PCを発売した。ビル・ゲイツはマーケット戦略が天才だと思う。現在でも、圧倒的にwindowsのシェアが高い。真似たって良いじゃないか。選択肢が増えて、使いやすければユーザーには関係ない。

# スティーブ・ジョブズ曰く、Stay hungry. Stay foolish
ところがネット業界のエンジニアでは、圧倒的にMacが多いです。CTOが集まるイベントでは、90%くらいがMacの印象。
もちろんMacがオシャレとかLinuxベースな事とか、使いやすいとかの色々な理由もあるが、iOSの開発がMacでしか出来ないというも大きな理由かも知れないと思います。スマホの世界では、圧倒的にiPhoneがシェア取ってます。

スティーブ・ジョブズは、
**他人の意見という雑音によって自分の内なる声がかき消されてしまわないようにしてください。そして、最も重要なことですが、自分の心と直感に従う勇気を持ってください。あなたの心と直感は、あなたが本当は何になりたいのかを、どうしてだかすでに知っているのです。他のことはすべて二の次です。**
と言ってます。

# 作り出す時は直感、戦う時はマーケットヒヤリング
iPhoneの様なマーケットにない様な新しい斬新なプロダクトやサービスを作る時は、自分の直感を信じて突き進むのが良いのでしょう。この過程では、資金力がなくて破れてしまう事もあるだろうし、大手に邪魔されて終わってしまう事もあるでしょう。しかし直感を信じて進んだ先に誰も出来たなった未来が広がる。
一方、マーケットにある程度認知されているプロダクトやサービスは、マーケットの意見を聞くべきだ。がむしゃらにジョブスを真似て、直感を信じても失敗するだけだと思う。
DDDがわからない～過去の遺産～

# 先人の遺した遺産
世の中には、デザインパターンのようなプログラムの作り方の教え、過去のシステム開発で覚えた技術。こういった先人たちの叡智は過去の成功例なのでどんどん活用していきましょう。

# 過去に囚われてはいけない
過去の遺産を利用するときには、決まっているシステムを変更してまで使わないようにしましょう。無理に遺産を使おうとすると技術よりの設計になりすぎてしまい、**ズレ**が起きてしまいます。遺産を使うときには、なぜそれを使うべきなのか関係者全員が理解できてから使うようにしましょう。
UTM "EFI stub: Exiting boot services messages..."に関するメモ

多分UTMでUbuntuを起動した直後にboot画面でVMをkillしちゃったせいで
"EFI stub: Exiting boot services messages..."から動かなくなった。
またやりそうなのでメモ。

以下のURLにそってやればOK

https://github.com/utmapp/UTM/issues/2682#issuecomment-1122193018
ループ処理【GitHubActions】

# やりたいこと
GitHubActionsのワークフローで、繰り返し処理を実装したい。

# やりかた
`strategy`句を使用する。

```yaml
jobs:
    sample-job:
        runs-on: ubuntu-latest
        strategy:
            matrix:
                aaa: [hoge, fuga]
        
        steps:
            - name: sample
              run: |
                echo "${{ matrix.aaa }}"  
```

# 参考
- [GithHub Actions / Using workflows / Workflow syntax / jobs.job_id.strategy.matrix](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix)
CentOS Stream 9類のLVMで既存のpvが無視される件

### 前置き

最近やっとCentOS8のサーバーをCentOS Stream 9に置き換えて本格的に使い始めました。

RockyLinuxやAlmaLinuxもCentOS8からのマイグレーションということでは大変ありがたいのですが、じゃあそのまま9にして使うかというと悩ましく、悩ましいぐらいなら正統な方に属するCentOS Stream 9を使おうかと思った次第です。最悪AlmaLinux9とかにマイグレーションできるみたいだし…

CentOS Stream 9やRHEL9クローンは体感では、ほぼ同じバージョンのカーネルを採用しているUbuntu 22.04より快適です。理由がx86_64-v2特化やもっと深いところにあるのか、単にコンソールの表示が速いだけなのか、単に新品のパンツを履いたときぐらいのお気持ちなのかは不明。あとすべてにおいて速いというわけではなさそうですね。

* x86_64-v2（日本語） https://rheb.hatenablog.com/entry/x86-64-v2

* （アプリケーションサーバーではなく）インフラ基盤としては良さそうなパフォーマンス（英語）
https://www.phoronix.com/review/centos-stream-9

ただ、使ってみると、古いOSで使っていたLVMのディスクを認識してくれていないことに気付きました。

### lvもvgもpvも出てこない
再起動とかアップデートとかそのうち何かのタイミングで出てきてくれるのかなと思いきや、一向に出てきませんし、何もエラーも出しません。lvs, vgs, pvs, pvscanでも出てきません。

`--devices`オプションでPVがあったところを強制的に指定してやると何とか出てきます。なので、`/dev/sdc`がそのデバイスだったとして、その状態で無理やりactivate

```
vgchange -ay Old_VG --devices /dev/sdc
```

とかするとmountすることもできるのですが、mountした状態ですら、pvもvgもlvも出てきません。
これはなかなか困ります。

なお、新規にpvcreateすると普通に出てきます。ここだけ見ると、まるでバージョンアップで新旧のLVMに互換性が無くなったような動作なので、驚いて作り直したりしないようにしましょう。

### 原因

というわけで原因です。公式ではないのですが、[こちら](https://portal.nutanix.com/page/documents/kbs/details?targetId=kA07V000000LaGrSAK)によると、RHEL9から、pvの検索には
`/etc/lvm/devices/system.devices` ファイルのリストを使うようになったとのこと。

公式に近いところで唯一見つけられたのはBugzilla。
https://bugzilla.redhat.com/show_bug.cgi?id=2012830

いずれにせよ解決策は次の通りです。

### 解決策

#### 方法その1) 昔と同じ挙動にする

メンテナンス用のマシンで、いろんなディスクを動的に付けたり外したりして認識してほしいというときには、昔と同じように動いてほしいものです。

`/etc/lvm/devices/system.devices`を使わないようにして、昔と同じ動作をさせるには、`lvm.conf`で`use_devicesfile=0`を設定すると良いようです。
CentOS Stream9の`lvm.conf`ではコメントアウトされているのでアンコメントすればよいですね。

```ini:/etc/lvm/lvm.conf（抜粋）
# Configuration option devices/use_devicesfile.
# Enable or disable the use of a devices file.
# When enabled, lvm will only use devices that
# are lised in the devices file. A devices file will
# be used, regardless of this setting, when the --devicesfile
# option is set to a specific file name.
# This configuration option has an automatic default value.
# use_devicesfile = 0
```

なお、CentOS8やUbuntu22.04のlvm.confにはそもそもエントリーがありませんでした。Ubuntuはコマンドもないので、非対応っぽいですね。上記のBugzillaによるとCentOS8.5からサポート（CentOS8だとデフォルトオフ）かな。

#### 方法その2) 正しい使い方をしてみる

新しいやり方には正しい使い方が当然用意されています。こっちの方が良い結果が期待できそうです。新しすぎるとバグを踏む確率も上がるかもしれないですが…

`/etc/lvm/devices/system.devices`にエントリを追加するためのコマンドは次の通りです。

`/dev/sdc`がそのデバイスだったとして
```
lvmdevices --adddev /dev/sdc
```
またはデバイスを指定しないでやってくれる
```
vgimportdevices -a
```

`vgimportdevices`は、指定された（またはすべての）vgに対して`lvmdevices --adddev`を使うと書かれているので、余計なものを巻き込まない限りはどちらでも同じ結果になるはずです。
https://man7.org/linux/man-pages/man8/lvmdevices.8.html
https://man7.org/linux/man-pages/man8/vgimportdevices.8.html

普段はアップデート後にこれを実行するだけでよさそうですね。

### 感想

あんまり情報ないあたり、もうRHEL9互換ディストリかつ手作業かつベアメタル運用なんてのは希少of希少なんでしょうね。クラウドだとほぼLVM使わないだろうし…
DDDがわからない～なんでも出来る人～

# みんなに頼られるすごい奴
各グループで同じことをしたい場合、グループに属さずに必要な場合に呼び出される人が出来上がってしまいます。

# みんなが頼りすぎてしまいがち
こういった人がいると、少しづつ欲が出てきてどんどん別の仕事も頼むようになってきてしまいます。そうなってくるとせっかく手分けしたはずなのにいつの間にか一人の人間の作業が多くなってしまいます。

# 作業分担の見直し
こういった作業過多になってしまうのは、開発当初にはわからないことが多いです。ひとりひとりの作業量に気を配り、多くなってしまった場合には早めに作業分担を見直しましょう。
pull_requestイベントについて【GitHubActions】

# 知りたいこと
GithubActionsの、ワークフローtriggerイベントの一つである「pull_request」であるが、これはつまりPRがどうなったときにワークフローが発火するのか？

# 答え
- デフォルトでは、「PRがopenされたとき」「PRにcommitがpushされたとき」「PRがcloseされたあと再度openされたとき」にワークフローが起動する。
- 以下のようにActivity typeを指定してあげれば、デフォルト以外を設定可能。
  - 設定できるタイプは[公式ドキュメント](https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#pull_request)および[こちらのブログ](https://frontside.com/blog/2020-05-26-github-actions-pull_request/)を参照。後者のブログは特にわかりやすかった。

```yaml
on:
  pull_request:
    type: [review_requested, review_request_removed]
```

# 参考
- [Events that trigger workflows  pull_request - Github Actions](https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#pull_request)
- [GITHUB ACTIONS: A DEEP DIVE INTO PULL_REQUEST](https://frontside.com/blog/2020-05-26-github-actions-pull_request/)
初心者がAWS lambdaを使ってみたお話

初心者がAWS lambdaを使ってみた感想。
# AWS lambdaとは
Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを関数として実行できるサービスです。
関数とは・・・中学校の数学の関数、y=f(x)を想像してください。（懐かしい）
![Screenshot_20221119_161402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933408/8c016890-457d-7dcd-11e4-b3d3e2c6e15b.png)
左からxが来てます。真ん中の四角が関数のf(x)。で、右側にyが出力されています。
つまり、xが何らかのブラックボックスf(x)を通るとyに変換されて出てくるわけですね。この四角のf(x)の部分がlambdaです。
左のxはトリガー、右のyは送信先になります。
# サーバレスって言ったって・・・
lambdaはサーバーレスであるのが特徴で、EC2とかにデプロイする必要がありません。ですが、実際にはそれを意識させないだけで、どこかの仮想環境に関数が乗っかって動作しています。
わざわざEC2にデプロイするほどでもない、小さな処理（関数）を組み合わせて使うのがこのlambdaの使い方です。大きく複雑な処理だとEC2にデプロイしたほうがいいと思います。AWSのサービスの橋渡し、Aサービス → Bサービスの中間に使うような使い方です。
# lambdaの餡子の部分
lambdaというまんじゅうの餡子の部分(処理するコード)をどうやって書くかですが、これだけ選択肢があります。
![Screenshot_20221119_162851.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933408/f06bddf5-ef3b-6931-a9f2-9fefb452ef93.png)
ここで注意しないといけないのは「ランタイム」のしたの注意書き書かれていることです。
この中でコンパイルが必要な言語(Java、.Net等)はlambdaのコードエディタではサポートされません。つまり、自分で別に、Eclise、VisualStudio等でコードを書いて、コンパイル/ビルドして、それをアップロードする必要があるので、AWS Consoleの中で完結しません。
それでは、折角のlambdaの小回りの効く機動力が活かせませんので、おそらくAWSとしては、Node.js、Python、Rubyあたりを推奨しているのではと思います。
ちなみに、Javaでまんじゅうの餡子を作ろうとするとこれだけの手順が必要になります。
[AWS Lambda + Java で Hello World](https://qiita.com/niwasawa/items/69bba64d7cd2d6277473)
# とりあえず、Pythonで関数を作ってみる
とりあえず、Pythonで関数を作ってみるとこのような感じになります。
![Screenshot_20221119_164352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933408/70c1996f-4e36-7595-6659-68d3cad025ac.png)
図の上側の「MyFunction」がまんじゅうの餡子の部分です。そのコードがその下に出ています。
上の図の左側「トリガー」が最初に書いたy=f(x)の関数の図の左側、xに相当します。
右側の「送信先」が関数の結果、y=f(x)のyに相当します。
# トリガーには何がある？
トリガーはAWSのサービスが選択できます。
![Screenshot_20221119_164838.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933408/64826c56-062a-0956-a09e-039c1cd584e5.png)
[AWS EventBridge](https://aws.amazon.com/jp/eventbridge/faqs/#:~:text=Q%3A%20Amazon%20EventBridge%20%E3%81%A8%E3%81%AF,%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%A7%E3%81%99%E3%80%82)も選択できます。
AWS EventBridgeとは、SaaSから発生するイベントを使用して、さらに様々なAWSサービスとつなげるまさしくBridge(架け橋)のようなサービスです。なのでlambdaでやろうとしていることのある程度の定型的パターンが用意されているようなものだと思います。
# 送信先には何がある？
送信先には大きく分けて2種類あります。
![Screenshot_20221119_165609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933408/b4c83d48-6f79-05ff-661f-b9bdbfc739ad.png)
- 非同期呼び出し
  非同期呼び出しはqueueか次のlambdaを指定できます。
  1. SNSトピック(メールを送信する場合)
  1. SQSキュー（Queueに入れて処理する場合）
  1. lambda（次のlambdaに数珠つなぎ）
  1. EventBridgeイベントバス（上記を参照）
- ストリーム呼び出し
  ストリームは非連続できたものを蓄積する系なのでDBになります
  1. Kinesis
  1. DynamoDB
  
# 最後にlambdaに思うこと、lambdaの使いみちは？
以上のことを考慮するとlambdaのコードの部分はあまり複雑な処理は向いていません。AWS ConsoleのlambdaのコードエディタもEclipseのようなコード補完機能はありますが、あまり期待はできません。本当にサービスからサービスへの橋渡しに使うものだと思います。
あるいは、アンケートの投票、いいねしたクリックをDBに蓄積するとか、そういう使い方なのかなと思います。

lambdaのコンセプト、メリットはわかりましたが、関数が数個〜10個くらいであればどの関数がどのようにつながっているか把握はできますが、これが数百となるとどうやって管理するんだろう？
関数にフォルダやネームスペース的なものはないし、関数名だけで区別しろってことなんだろうか？VPCに紐付けることはできるけど、それだけじゃ不足じゃないだろうか？
ブランチによって処理を変える【GitHubActions】

# やりたいこと
GitHubActionsのワークフローにおいて、push先ブランチによって、処理を変更する。

# 実装方法
push先が、devブランチのときとmainブランチのときで、設定する環境変数の値を変える例を実装する。
以下のように、stepのif句で `github.ref_name` で条件を書いてあげればOK。

```yaml
name: sample-workflow

on:
  push:
    branches: [dev, main]

jobs:
  sample-job:
    runs-on: ubuntu-latest

    steps:
      - name: Set dev value
        if: ${{ github.ref_name == 'dev' }}
        run: |
          echo "ENV=dev" >> $GITHUB_ENV

      - name: Set prd value
        if: ${{ github.ref_name == 'main' }}
        run: |
          echo "ENV=prd" >> $GITHUB_ENV
```
（備忘録）Microsoft Power Platform の全体像をざっくり理解

# 1. はじめに
今回は、自分自身への備忘録を兼ねて、Microsoft Power Platformの全体像について学んだことを、ざっくりお伝えしたいと思います

# 2. この記事を読んでできること
- Microsoft Power Platform の全体像を理解できるようになる

# 3. Power Platform とは
- 4つのサービス
	- Power Apps（ビジネスアプリ開発）
	- Power Automate（プロセス自動化）
	- Power BI（リアルタイム分析）
	- Power Virtual Agents（チャットボット開発）

- 標準データ保管領域
	- Dataverse（データバース）

- サービス連携
	- コネクタ（他サービスと簡易接続）

- セットアップ済みAI群
	- AI Builder（すぐに利用可能なAIサービス群）

- ローコード言語
	- Power Fx

# 4. Power Apps とは
- Webアプリを開発できるサービス

- 作成できるWebアプリの種類
	- キャンバスアプリ（白紙キャンバスにドラッグ＆ドロップで開発）
	- モデル駆動型アプリ（Dataverseをもとに作るビジネスアプリ、ノーコード開発可能）
	- Power Appsポータル（Webサイトテンプレート、SNS認証利用可能、認証認可機能利用可能）

# 5. Power Automate とは
- 反復可能な業務の自動化アプリを開発できるサービス

- 2つのサービス
	- Power Automate（オンライン操作の自動化）
	- Power Automate for Desktop（オフライン操作の自動化）

- テンプレート
	- テンプレートを活用した開発が可能

# 6. Power BI とは
- 企業データのリアルタイム分析をサポートするサービス

- 機能
	- クロスフィルター機能

# 7. Power Virtual Agents とは
- チャットボットを開発できるサービス

# 8. Dataverse とは
- Power Platformの各サービスから利用可能なデータベース

# 9. AI Builder とは
- 専門知識がなくても利用可能なAIサービス

- 利用可能なAIサービス
	- 物体検出AI
	- 抽出分類AI
	- OCRテキスト抽出AI

# 10. おわりに
今回の記事が、みなさまの学習の参考になれば幸いです

2022/11/19 NISHIZONO Takahiro

---
システムの活用促進

# システムやデータの活用促進　
システムやデータを業務や経営に活かすには、それを活用するために必要なスキルを、```社員一人一人が習得できる環境作りも重要```になってくる。

## 情報リテラシ
コンピュータやアプリケーションソフト、ネットワークなどを活用し、業務に必要な情報を効果的に検索し、精査・分析するなど、```情報技術を効果的に活用する能力```のこと。

### ディジタルディバイド(digital divide: 情報格差)
```情報格差```とも言う。ITを利用するスキルや、利用機会の違いによって生じる経済格差、特に、```インターネットの恩恵を受けることのできる人とできない人との間に生じる```。

## 情報システム利用実態の評価・検証
情報システムが計画どおりに```利用される```か、```パフォーマンスや信頼性が落ちて```いないかを把握する。また、```必要であれば改善目標を定める```。

### BYOD(Bring Your Own Device)
```許可を得て、私物のパソコンやスマートフォン、私的なクラウドサービスなどを、業務に使用したり社内ネットワークに接続```すること。
ウイルスに感染したり、データが持ち出されることによる情報漏洩のリスクがある。
なお、```無許可でBYODを行うことをシャドーIT```という。

### ビッグデータ
Webサイトなどさまざまな```リソースから収集された、多様な形式（テキストや画像、音声など）```などのデータのこと。蓄積した```大量の情報を分析・活用```することで、経営判断や意思決定に役立つことが期待されている。

# 活用促進のための手法
### ゲーミフィケーション(gemification)
```ある行動を誘発したり継続させるために、ゲーム的要素を取り入れる```こと。システム活用の場面なら、システムの操作習得用の動画視聴にポイントを付与、操作をクイズにしてレベル認定など、```楽しみながらモチベーションを高める```工夫などが考えられる。

### BI(Business Intelligence)ツール
蓄積されたさまざまな形式のデータを収集・分析し、結果を```グラフや表などに加工するツール```。データ分析の専門知識がなくても、```簡単な操作で目的に合った分析処理```が可能。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
exec /usr/local/bin/docker-entrypoint.sh: exec format error

# `exec /usr/local/bin/docker-entrypoint.sh: exec format error`にハマる
AWS　ECRへプッシュ後、AWR　ECSから起動しようとするとどうしてもコケる。
## 原因
イメージ作成時に稼働プラットフォームを指定すべきであった。
```shell
docker build --platform linux/amd64 . -t test_ecr:latest
```
@csrfについて


現在独学でLaravelを使用し、簡単な掲示板を作成しています。
掲示板を作成していくなかで、投稿や編集画面でフォームを作成する際formタグの中に@csrfを記載することで、CSRF攻撃を防げる機能がLaravelには備わっておりました。
CSRF攻撃とはそもそも何？というところから、@csrfと記載する事でどのような処理を行なってくれているのかという所までご紹介させていただきます。
理解を深める意味と備忘を兼ねて投稿をさせていただきます。


## ●そもそもCSRFとは
##### 正式名称:cross-site request forgeries（クロスサイトリクエストフォージェリ）
CSRFとは、Webアプリケーションに存在する脆弱性、もしくはその脆弱性を利用した攻撃方法のことです。
ユーザーが悪意のあるURLにアクセスしてしまった場合に、意図しないリクエストを特定のWebサービスに送られてしまうというものです。掲示板であれば意図しない投稿や、オンラインバンキングであれば意図しない送金処理などが他者によって行われてしまうみたいですね。
恐ろしすぎる。。。

## ●@csrfについて
上記の攻撃を簡単に保護してくれるのが、@csrfです。
使い方は、
Laravelでformタグを記載した際は、必ず@csrfを記載する。
以上です。
簡単すぎます。
むしろ記載しないと419エラーが返ってきてしまいます。

行っている内容としては
Laravelはリクエスト毎にトークンと呼ばれるランダムな文字列を生成します。
クライアントは次回のリクエスト時に発行されたトークンをサーバーに送り返します。
サーバーはトークンを受け取り、発行したトークンと照合します。トークンの文字列が合致する場合、正当なユーザーからのリクエストとみなして処理を続行します。

<br>

__①サーバーサイドで、40字のランダムな文字列データ(暗号)を生成します。 ※後でこの値とフォームから送られてくる_csrfの値を照合する__

__②暗号の値をセッションへ保存します__

__③暗号の値を読み取ります__
@csrfを記載することで、<form>内の<input name= “_token”>のvalueにトークンをセットします。hiddenのためサイト上は見えません。
```
<input type="hidden" name="_token" value="Q9fYbbZYy8dK4p9RiMdfOsnDuTnwMTq91kAFbu60">
```


__④ブラウザはリクエストを投げます__

__⑤サーバー側は暗号化して保持している値とリクエストのトークンの内容が一致するかをチェックします。__

__⑥チェックが完了したら、レスポンスヘッダーに、Cookieをセットしてブラウザに返す。__


## ●被害実例
被害の一つとして **『横浜CSRF事件』** と呼ばれるサイバー犯罪が過去に存在するようです。
横浜CSRF事件では、CSRFの被害を受けたパソコンから、掲示板サービスに犯行の予告が書き込まれてしまいました。このリクエストを強要されたユーザーが誤認逮捕されてしまう事態が起きているそうです。
身に覚えのない投稿が自分のアカウントから書き込まれるなんて恐ろしすぎます。。

## 最後に
Laravelには標準で様々なディレクティブな用意されているので、今後もぜひうまく活用し製造の質とスピードを高めていきたいと思いました。