投稿者: sumito.tsukada

  • firebase deploy時のeslintを無効にする

    firebase deploy時のeslintを無効にする

    はじめに

    firebase functionを使えるようにした際、知らず知らずにESLintを有効にしてしまっていた。今回は対処した際の方法を紹介。

    問題

    firebase deploy
    
    === Deploying to 'auth-xxx'...
    
    i  deploying database, functions, hosting
    Running command: npm --prefix "$RESOURCE_DIR" run lint
    
    > functions@ lint /Users/coco/Documents/firebase-auth/functions
    > eslint .
    
    
    /Users/coco/Documents/firebase-auth/functions/index.js
      31:7   error    Expected return with your callback function                     callback-return
      38:24  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
    
    ✖ 2 problems (1 error, 1 warning)
    
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! functions@ lint: `eslint .`
    npm ERR! Exit status 1
    npm ERR! 
    npm ERR! Failed at the functions@ lint script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     /Users/coco/.npm/_logs/2019-12-10T15_36_22_429Z-debug.log
    
    Error: functions predeploy error: Command terminated with non-zero exit code1
    darkenagy:firebase-auth coco$ cat /Users/coco/.npm/_logs/2019-12-10T15_36_22_429Z-de

    ESLintで引っかかっているようだ。

    ふりかえり

    そもそも、本当にESLintを有効にしたんだっけ。。
    どのようにfirebase functionを有効にしたか振り返る。

    firebase init functions
    
         ######## #### ########  ######## ########     ###     ######  ########
         ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
         ######    ##  ########  ######   ########  #########  ######  ######
         ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
         ##       #### ##     ## ######## ########  ##     ##  ######  ########
    
    You're about to initialize a Firebase project in this directory:
    
      /Users/coco/Documents/firebase-auth
    
    Before we get started, keep in mind:
    
      * You are initializing in an existing Firebase project directory
    
    
    === Project Setup
    
    First, let's associate this project directory with a Firebase project.
    You can create multiple project aliases by running firebase use --add, 
    but for now we'll just set up a default project.
    
    i  .firebaserc already has a default project, using auth-xxx.
    
    === Functions Setup
    
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? JavaScript
    ? Do you want to use ESLint to catch probable bugs and enforce style? Yes
    ✔  Wrote functions/package.json
    ✔  Wrote functions/.eslintrc.json
    ✔  Wrote functions/index.js
    ✔  Wrote functions/.gitignore
    ? Do you want to install dependencies with npm now? Yes
    
    > protobufjs@6.8.8 postinstall /Users/coco/Documents/firebase-auth/functions/node_modules/protobufjs
    > node scripts/postinstall
    
    npm notice created a lockfile as package-lock.json. You should commit this file.
    added 344 packages from 245 contributors and audited 869 packages in 11.579s
    found 0 vulnerabilities
    
    
    i  Writing configuration info to firebase.json...
    i  Writing project information to .firebaserc...
    
    ✔  Firebase initialization complete!
    
    
       ╭───────────────────────────────────────────╮
       │                                           │
       │      Update available 7.8.1 → 7.9.0       │
       │   Run npm i -g firebase-tools to update   │
       │                                           │
       ╰───────────────────────────────────────────╯
    

    しっかりESLintを有効にしてた。

    現在の設定を確認

    firebase.jsonを確認する

    cat firebase.json 
    {
      "database": {
        "rules": "database.rules.json"
      },
      "hosting": {
        "public": "public",
        "rewrites": [
          {
            "source": "**",
            "function": "firebaseAuth"
          }
        ],
        "ignore": [
          "firebase.json",
          "**/.*",
          "**/node_modules/**"
        ]
      },
      "functions": {
        "predeploy": [
          "npm --prefix \"$RESOURCE_DIR\" run lint"
        ]
      }
    }

    黄色の箇所を削除し、再度“` firebase deploy“`を行うと、ESlintが行われずdeployされる。

    参考情報

  • laravelでDBの取得結果をviewに出す

    laravelでDBの取得結果をviewに出す

    はじめに

    viewへのデータの受け渡しについて、router,Controller,viewに分けて整理する。

    データベースの中身

    router

    <?php
    
    Route::get('/', 'PostsController@index');

    Controller

    <?php
    
    namespace App\Http\Controllers;
    
    use App\Post;
    
    class PostsController extends Controller
    {
        //
        public function index()
        {
            $posts = Post::all();
    
            // 意図的に空にする
            //$posts = [];
    
            // 両方同じ意味
           // return view('posts.index', ['posts'=> $posts]);
           return view('posts.index')->with('senddata', $posts);
    
        }
    }
    

    a

     view

    <!DOCUMENT html>
    
        <html lang="ja">
            <head>
                <meta charset="utf-8">
                <title>this is title</title>
            </head>
    
            <body>
                <div class='container'>
                    <h1> this is it!</h1>
                    <ul>
                        @forelse ($senddata as $data)
                        <li>{{ $data->title }}</li>
                        @empty
                        empty!
                        @endforelse
                    </ul>
    
                </dev>
            </body>
    
        </html>
    

    結果

    laravel の実践向け書籍

  • laravelでddを使ってdebugする

    laravelでddを使ってdebugする

    はじめに

    laravelで用意されている簡易的なdebugツールddを紹介。

    ddとは

    dump and dieの略。処理はここでデータを全て吐き出してくれて、処理は止まる。

    https://laravel.com/docs/master/helpers#method-dd

    データベースの中身

    以下のような状態だとする

     

    routerの設定

    <?php
    
    Route::get('/', 'PostsController@index');

    Controllerの設定

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Post;
    
    class PostsController extends Controller
    {
        //
        public function index(){
            $posts = Post::all();
            dd($posts->toArray());
    
            return view('posts.index');
        }
    }

    結果

     

    laravel の実践向け書籍

  • laravelのシンプルな機能でrouterとcontrollerとviewを繋げる

    laravelのシンプルな機能でrouterとcontrollerとviewを繋げる

    はじめに

    非常にシンプルな構成でlaravelのシンプルな機能でrouterとcontrollerとviewを繋げる

    router

    <?php
    
    Route::get('/', 'PostsController@index');

     

    Controller

    ディレクトリはドット(.)で区切られる事に注意

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class PostsController extends Controller
    {
        //
        public function index(){
            return view('posts.index');
        }
    }
    

    view

    “` resources/views “` 配下にpostsディレクトリを作成し、
    その中に “` index.blade.php “` を格納する

    <!DOCUMENT html>
    
    <html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>this is title</title>
    </head>
    
    <body>
     <div class='container'>
     <h1> this is it!</h1>
     </dev>
    </body>
    
    </html>

    結果

     

     

  • laravelのシンプルな機能でrouterとcontrollerを繋げる

    laravelのシンプルな機能でrouterとcontrollerを繋げる

    はじめに

    databaseにも繋げない、非常にシンプルな方法でrouterとcontrollerを繋げる

    routerの編集

    “` routes/web.php“`

    <?php
    
    /*
    |--------------------------------------------------------------------------
    | Web Routes
    |--------------------------------------------------------------------------
    |
    | Here is where you can register web routes for your application. These
    | routes are loaded by the RouteServiceProvider within a group which
    | contains the "web" middleware group. Now create something great!
    |
    */
    
    Route::get('/', 'PostsController@index');

    controllerの作成

    “` php artisan make:controller PostsController “`

     

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class PostsController extends Controller
    {
        //
        public function index(){
            return 'hello';
        }
    }
    

    結果

     

  • laravelでデフォルトのtimezoneの言語設定の変更

    laravelでデフォルトのtimezoneの言語設定の変更

    はじめに

    laravelでデフォルトのtimezoneの言語設定を変更したい場合がある。その変更方法を紹介。

    変更ファイル

    変更対象は “` config/app.php “`

    timezone

    変更前

    “` ‘timezone’ => ‘UTC’, “`

    変更後

    “` ‘timezone’ => ‘Asia/Tokyo’, “`

     

    言語設定

    変更前

    “` ‘locale’ => ‘en’, “`

    変更後

    “` ‘locale’ => ‘ja’, “`

     

     

  • laravel 5.5のディレクトリ構成

    laravel 5.5のディレクトリ構成

    はじめに

    laravelのディレクトリ構成について調べたのでまとめる

    tree結果

    ├── app     # MODELに関するファイルはapp直下に作られる
    │   ├── Console
    │   ├── Exceptions
    │   ├── Http
    │   │   ├── Controllers # Controllersに作られる
    │   │   ├── Kernel.php
    │   │   └── Middleware
    │   ├── Providers
    │   └── User.php # デフォルトで作られる。削除可能
    ├── artisan
    ├── bootstrap
    │   ├── app.php
    │   └── cache
    ├── composer.json
    ├── composer.lock
    ├── config # 設定に関するファイル
    │   ├── app.php # timezoneの設定、言語設定含む設定
    │   ├── auth.php
    │   ├── broadcasting.php
    │   ├── cache.php
    │   ├── database.php
    │   ├── filesystems.php
    │   ├── mail.php
    │   ├── queue.php
    │   ├── services.php
    │   ├── session.php
    │   └── view.php
    ├── database  # データベースに関するファイル
    │   ├── factories
    │   ├── migrations #データベースのversion管理のファイルが作られる
    │   │   ├── 2014_10_12_000000_create_users_table.php # デフォルトで作られる。削除可能
    │   │   └── 2014_10_12_100000_create_password_resets_table.php # デフォルトで作られる。削除可能
    │   └── seeds
    ├── package.json
    ├── phpunit.xml
    ├── public # ブラウザからアクセスされたら使われるフォルダ
    │   ├── css
    │   ├── favicon.ico
    │   ├── index.php
    │   ├── js
    │   ├── robots.txt
    │   └── web.config
    ├── readme.md
    ├── resources
    │   ├── assets
    │   ├── lang
    │   └── views #  画面のテンプレート
    ├── routes
    │   ├── api.php
    │   ├── channels.php
    │   ├── console.php
    │   └── web.php # ルーティング。webアプリケーションを利用する場合はこちらをいじる。
    ├── server.php
    ├── storage
    │   ├── app
    │   ├── framework
    │   └── logs
    ├── tests
    │   ├── CreatesApplication.php
    │   ├── Feature
    │   ├── TestCase.php
    │   └── Unit
    ├── vendor
    │   ├── autoload.php
    │   ├── bin
    │   ├── composer
    │   ├── dnoegel
    │   ├── doctrine
    │   ├── egulias
    │   ├── erusev
    │   ├── fideloper
    │   ├── filp
    │   ├── fzaninotto
    │   ├── hamcrest
    │   ├── jakub-onderka
    │   ├── kylekatarnls
    │   ├── laravel
    │   ├── league
    │   ├── mockery
    │   ├── monolog
    │   ├── mtdowling
    │   ├── myclabs
    │   ├── nesbot
    │   ├── nikic
    │   ├── paragonie
    │   ├── phpdocumentor
    │   ├── phpspec
    │   ├── phpunit
    │   ├── psr
    │   ├── psy
    │   ├── ramsey
    │   ├── sebastian
    │   ├── swiftmailer
    │   ├── symfony
    │   ├── theseer
    │   ├── tijsverkoyen
    │   ├── vlucas
    │   └── webmozart
    └── webpack.mix.js

     

     

  • laravelのtinkerを使ってデータを投入する

    laravelのtinkerを使ってデータを投入する

    はじめに

    laravelにはtinkerという機能があり、“` php artisan tinker “` コマンドを用いてデータを入れることができる。

    前提条件

    以下のようなテーブルがあったとする

    CREATE TABLE `users` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
      `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
      `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
      `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `users_email_unique` (`email`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

    “` app\User.php “` 配下のModele クラスに、
    ホワイトリスト形式で入力を受付けさせるようにする。

        protected $fillable = [
            'name', 'email', 'password',
        ];

    “` fillable “` で宣言されたカラムがホワイトリストとして機能し、これらのカラムにデータの投入が許可される。

    逆にブラックリスト形式で制御したい場合は “` guarded “` という変数名を利用する 

    データ投入

    tinkerを起動する

    php artisan tinker
    Psy Shell v0.9.11 (PHP 7.2.25 — cli) by Justin Hileman
    >>>

    の画面が出たら、以下の通り投入したいデータを入力

    post = App\User::create(['name'=>'tsukada hoge','email'=>'hoge@sumito.jp','password'=>'cccc']);

    動作確認

    データを確認すると無事投入された

     

    sample

    以下のようにデータを投入する場合は、

    “` app\User.php “` 配下のModele クラスを編集する必要はない。

    $ php artisan tinker
    Psy Shell v0.9.12 (PHP 7.2.25 — cli) by Justin Hileman
    >>> $post = new App\Post();
    => App\Post {#2894}
    >>> $post->title = 'title hogehoge';
    => "title hogehoge"
    >>> $post->body = 'body hogehoge';
    => "body hogehoge"
    >>> $post->save();
    => true
    >>>

    データを確認したい場合

    “` App\Post::all(); “` 

    PostはMODEL名

    >>> App\Post::all();
    => Illuminate\Database\Eloquent\Collection {#2903
         all: [
           App\Post {#2904
             id: 1,
             title: "title 1",
             body: "body 1",
             created_at: "2019-12-09 15:02:27",
             updated_at: "2019-12-09 15:02:27",
           },
           App\Post {#2905
             id: 2,
             title: "hogehoge",
             body: "body hogehoge",
             created_at: "2019-12-09 15:04:21",
             updated_at: "2019-12-09 15:04:21",
           },
         ],
       }
    >>>

    以下のように投入する場合は、エラーが発生する

    >>> App\Post::create(['title'=>'title 2', 'body'=>'body 2']);
    Illuminate/Database/Eloquent/MassAssignmentException with message 'title'
    >>>

    この場合は、“` app\User.php “` 配下のModele クラスを編集することで、投入を許可する。

    ※ “` app\User.php “` を編集した後は、tinkerに入り直す必要がある。

    $ php artisan tinker
    Psy Shell v0.9.12 (PHP 7.2.25 — cli) by Justin Hileman
    >>> App\Post::create(['title'=>'title 2', 'body'=>'body 2']);
    => App\Post {#2892
         title: "title 2",
         body: "body 2",
         updated_at: "2019-12-09 15:11:31",
         created_at: "2019-12-09 15:11:31",
         id: 3,
       }
    >>>

    無事入力できた

    >>> App\Post::all()->toArray();
    => [
         [
           "id" => 1,
           "title" => "title 1",
           "body" => "body 1",
           "created_at" => "2019-12-09 15:02:27",
           "updated_at" => "2019-12-09 15:02:27",
         ],
         [
           "id" => 2,
           "title" => "hogehoge",
           "body" => "body hogehoge",
           "created_at" => "2019-12-09 15:04:21",
           "updated_at" => "2019-12-09 15:04:21",
         ],
         [
           "id" => 3,
           "title" => "title 2",
           "body" => "body 2",
           "created_at" => "2019-12-09 15:11:31",
           "updated_at" => "2019-12-09 15:11:31",
         ],
       ]
    >>>

    条件付きのデータ取得

    x件目のデータを取得

    >>> App\Post::find(3)->toArray();
    => [
         "id" => 3,
         "title" => "title 2",
         "body" => "body 2",
         "created_at" => "2019-12-09 15:11:31",
         "updated_at" => "2019-12-09 15:11:31",
       ]
    >>>

    whereを使ったデータ取得

    >>> App\Post::where('id', '>', 2)->get()->toArray();
    => [
         [
           "id" => 3,
           "title" => "title 2",
           "body" => "body 2",
           "created_at" => "2019-12-09 15:11:31",
           "updated_at" => "2019-12-09 15:11:31",
         ],
       ]
    >>>

    orderByを用いた並び替え

    >>> App\Post::where('id', '>' , '1')->orderBy('created_at', 'desc')->get()->toArray();
    => [
         [
           "id" => 3,
           "title" => "title 2",
           "body" => "body 2",
           "created_at" => "2019-12-09 15:11:31",
           "updated_at" => "2019-12-09 15:11:31",
         ],
         [
           "id" => 2,
           "title" => "hogehoge",
           "body" => "body hogehoge",
           "created_at" => "2019-12-09 15:04:21",
           "updated_at" => "2019-12-09 15:04:21",
         ],
       ]
    >>>

    SQLのlimit

    >>> App\Post::where('id', '>' , '1')->get()->take(1)->toArray();
    => [
         [
           "id" => 2,
           "title" => "hogehoge",
           "body" => "body hogehoge",
           "created_at" => "2019-12-09 15:04:21",
           "updated_at" => "2019-12-09 15:04:21",
         ],
       ]
    >>>

     

     

    laravel の実践向け書籍

  • Firebase AuthenticationにFacebook Accountでログインする

    Firebase AuthenticationにFacebook Accountでログインする

    はじめに

    Firebase AuthenticationにFacebook Accountでログインを有効にさせる方法をまとめます。

    設定

    Facebook for Developers(以下Facebook)にログインして、アカウントのセットアップをします

    https://developers.facebook.com/?locale=ja_JP

     

    Firebaseのログインプロバイダの画面で「Facebookログイン」を有効にします。

    Facebook側のページに戻り、左側の設定のからベーシックを押し、アプリID/app secretを確認します。

    Firebase側に戻り、それぞれ埋めます。

    Facebookでクイックスタートからウェブを選択します。

    WebアプリケーションのURLを入力。

    Firebaseの画面に表示されているOAuth リダイレクト URI を Facebook アプリの設定に追加します。

    以上で設定は完了です。

    Signin

    自作のアプリケーションからSigninします

    Facebookログインを試みると、

    よく見るFacebookの承認画面が表示され、ログインを押すと、無事アプリケーションにログインできるようになりました。

    注意すべきところ

    接続元の環境がhttp

    ローカルで開発しているので、http://localhost/ で確認していたのですが、httpでFacebookログインを試みると

    Facebook側で以下のようなアラートが出て、invalid_request

    無視して進めたところ認証エラーが。

    Error getting verification code from facebook.com response: error=invalid_request&error_code=191&error_description

    というエラーが表示されるようになりました。

    その対策としてFirebase Hostingへdeployして、httpsで接続できるようにした上でFacebookとの接続をするようにしました。

    メールアドレスの重複

    既に他のソーシャルアカウントでログインした後に、Facebookアカウントでログインを試みるとエラーが。。

    An account already exists with the same email address but different sign-in credentialsSign in using a provider associated with this email address

    どうやらFirebaseのデフォルトの動きとしてソーシャルアカウントに登録したメールアドレスが、他のソーシャルアカウントで使っている場合、「既に登録してある」と見なされアカウント作成できないようです。

    もちろんFirebaseで承認したアカウントを削除することで、Facebookアカウントでログインできるようになりました。

     

    しかし、やはりユーザーによっては複数ソーシャルアカウントが同一メールアドレスで登録している人も少なくありません。

    設定変更画面から複数メールアドレスの登録を許可させることができます。

    デフォルトでは上段が選択されていますが、下の「複数のアカウントを作成できるようにする」を選択します。

    Google認証に加え、Facebookアカウントでもログインできるようになりました。
    登録アカウントは以下の通り。

    Firebaseはシンプルな認証機能を提供してくれるので、これからアプリケーションを作っていくという場合は最適な選択肢になるのではないでしょうか。

     

     

  • firebase authenticationでユーザーのimport/exportについて調べた

    firebase authenticationでユーザーのimport/exportについて調べた

    はじめに

    Firebase Authentication は、firebase での認証処理を行うための機能です。
    ID/PWによるパスワード認証、電話番号認証、Google、Facebook、Twitterなどソーシャルアカウントを使用した認証を行うことができます。

    本記事はfirebase authenticationでユーザーのimport/exportについて調べました。

    firebase authenticationの責務について

    責務としては認証までです。
    認可については本機能のスコープ外になります。

    詳細は以下参考

    https://apps-gcp.com/firebase-authentication/

     

    コンソール画面での見え方について

    コンソール画面にcsv/json形式でimportする機能があっても良さそうですが、残念ながらそのボタンは見当たりません。

    青い「ユーザーを追加」ボタンを押しても、メールアドレスとパスワードを入力する画面が表示されるのみです。

    対応

    firebase cliを使うことで、具体的には “` firebase auth:import “` コマンドを使うことでimportが可能ということが分かりました。

    https://firebase.google.com/docs/cli/auth-import#syntax

    firebase cliのinstall方法はこちら

    https://firebase.google.com/docs/cli?hl=ja

    jsonファイルを作成する

    試しにtwitter認証アカウントを2つ、Google認証というアカウントを1つ。合計3ユーザーを作成することにします。

    {
      "users": [
        {
          "localId": "1",
          "email": "ec@sumito.jp",
          "emailVerified": null,
          "passwordHash": null,
          "salt": null,
          "displayName": "test1",
          "photoUrl": null,
          "providerUserInfo": [
            {
              "providerId": "twitter.com",
              "rawId": "xxxxxxxxxxxx",
              "email":  null,
              "displayName": "test1",
              "photoUrl": null
            }
          ]
        },
        {
          "localId": "2",
          "email": "sute@sumito.jp",
          "emailVerified": null,
          "passwordHash": null,
          "salt": null,
          "displayName": "test2",
          "photoUrl": null,
          "providerUserInfo": [
            {
              "providerId": "twitter.com",
              "rawId": "xxxxxxxxxxxx",
              "email":  null,
              "displayName": "test2",
              "photoUrl": null
            }
          ]
        },
        {
          "localId": "3",
          "email": "mitsuisumito.viva@gmail.com",
          "emailVerified": true,
          "displayName": "sumito tsukada",
          "photoUrl": "https://lh3.googleusercontent.com/a-/xxx,
          "providerUserInfo": [
            {
              "providerId": "google.com",
              "rawId": "1234",
              "email": "mitsuisumito.viva@gmail.com",
              "displayName": "sumito tsukada",
              "photoUrl": "https://lh3.googleusercontent.com/a-/xxx"
            }
          ]
        }
      ]
    }

     今回はuser.jsonという名前で保存し、読み込ませます。

    $ firebase auth:import ./user.json --hash-algo=HMAC_SHA256  --hash-key=hogehoge
    Processing ./user.json (1451 bytes)
    Starting importing 3 account(s).
    ✔  Imported successfully.
    

    今回はハッシュアルゴリズムをHMAC_SHA256にしましたが、適宜変更してください。

    firebase authentication上でimport確認

    無事importされたようです。

    ちなみに、デフォルトでFirebase authenticationを使いアカウント作成すると、ユーザーUIDはランダム数字になりますが、import形式では任意のIDを指定することができるようです。

    動作確認

    自作のアプリケーションのログイン画面からログインを試みます。

    無事ログインできたようです。

    無事ログイン日時も記載されました

    export

    firebase authenticationに登録されたユーザーは“` firebase auth:export “` コマンドでexportすることができます

    $ firebase auth:export hogehoge --format=json
    Exporting accounts to hogehoge
    ✔  Exported 3 account(s) successfully.

    所感

    firebase authenticationを使えば既存システムからの移行も現実的に見えるかもしれません。
    とはいえ、まだまだ調査すべきところは山のようにあるので、一つ一つ調べていこうと思います。