daikiojm’s diary

ブログを書くときがやってきたどん!

connect-mongoをサクッと試す

社内勉強会で「Node.jsを使って社内で使える便利ツールを作ろう」というテーマで簡単なWebアプリケーションの作成を行っている。

Express+MongoDB+ejs(ほぼjQuery)で最低限の機能を実装したモノは出来上がったものの、ユーザー認証機能が未実装のままだったので、ちょっと残念な感じになっていた。

Express ユーザー認証とかで検索すると、Passportというパッケージを使うのが定跡なように感じたが、あまり頑張らずにサクッとユーザー認証機能を実装したかったので、今回はconnect-mongoというパッケージをサクッと試してみることにした。

Expressで認証を設定するプロジェクトの雛形を作成する

事前にexpress-generatorのインストールをしてある前提で、プロジェクトの雛形を作成し、動作確認を行います。 テンプレートエンジンにはejsを使用した。

$ mkdir connect-mongo-skt && cd connect-mongo-skt
$ express -e .
$ npm install
$ npm start

今回想定するログインのシナリオは、以下の通りです。

未ログイン時
* ルートへのアクセス
↓(リダイレクト)
* ログイン画面
↓(ログイン)
* ユーザーページ

ログイン時
* ルートへのアクセス
↓(リダイレクト)
* ユーザーページ

ユーザー認証に成功すると、ユーザーページへアクセス可能になるという動作に必要なrouterとviewの作成を行います。 express-generatorで作成した雛形には以下のように、indexとusersページが作成されているので、

  • index → ログイン画面
  • users → ログイン認証に成功されたら表示する画面

追加で、以下のviewを作成しました。(コードは後述)

  • login → ログイン前にindexのrouterから呼ばれる

※現時点ではhttp://localhost:3000/usersというアドレスでusersページにアクセス出来る

connect-mongoを導入

必要パッケージのインストー

$ npm install --save connect-mongo
$ npm install --save express-session
$ npm install --save mongoose

app.jsの変更

パッケージの読み込みとmongooseコネクションの確立

const mongoose = require('mongoose');
const session = require('express-session');
const mongoStore = require('connect-mongo')(session);

// localhost:27017 でMongoDBが起動している前提
mongoose.connect('mongodb://localhost:27017/connect-mongo-skt');

sessionを使うための準備

app.use(session({
  secret: 'test', 
  store: new mongoStore({ mongooseConnection: mongoose.connection })
}));

後でindex内でルーティングの設定を一括して行うため以下の部分はコメントアウトします。

// app.use('/users', users);

mongooseのスキーマ定義

$ mkdir models
$ touch models/userModel.js
const mongoose = require('mongoose');
let Schema = mongoose.Schema;

let UserSchema = new Schema({
  username: String,
  password: String,
});

module.exports = mongoose.model('Users', UserSchema);

index.jsの変更

ModelとViewファイルの読み込み

let User = require('../models/userModel.js');
let users = require('./users.js');
router.get('/', function(req, res, next) {
  // debug
  console.log(req.session);
  if (req.session.user) {
    // すでにログイン時
    res.redirect('/users')
  }
  res.render('login', { title: 'Express' });
});

/* ログイン */
router.post('/login', function(req, res, next) {
  // 簡単なバリデーション
  if (!req.body.username || !req.body.password) {
    res.redirect('/');
  }
  let query = {
    username: req.body.username,
    password: req.body.password // sha1などで暗号化するのがベター
  }
  User.find(query, function(err, data) {
    if (err) {
      // エラー発生時
      console.log(err);
      res.redirect('/');
    }
    if (data.length > 0) {
      // ログイン成功時
      req.session.user_id = data[0]._id;
      res.redirect('/users');
    }
    else {
      // ログイン失敗時
      res.redirect('/');
    }
  });
});

router.post('/register', function(req, res) {
  // 簡単なバリデーション
  if (!req.body.username || !req.body.password) {
    res.redirect('/');
  }
  let user = new User();
  user.username = req.body.username;
  user.password = req.body.password;
  user.save(function(err) {
    if (err) {
      console.log(err);
    }
    res.redirect('/');
  });
});

router.post('/logout', function(req, res) {
  delete req.session.user;
  res.redirect('/');
});

let loginCheck = (req, res, next) => {
  if (req.session.user_id) {
    next();
  } else {
    res.redirect('/');
  }
}

router.use('/users', loginCheck, users); // loginCheck

ログイン画面

サクッと試す目的で作成したため、ログイン画面とユーザー登録画面が単一になっています。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <h2>ログイン</h2>
  <form action="/login" method="POST">
    <input type="text" name="username"/>
    <input type="password" name="password"/>
    <input type="submit">ログイン</button>
  </form>

  <h2>新規登録</h2>
  <form action="/register" method="POST">
    <input type="text" name="username"/>
    <input type="password" name="password"/>
    <input type="submit">登録</button>
  </form>

</body>
</html>

以上、connect-mongoを使ってログイン機能をサクッと実装することが出来ました。

GitHub

github.com

Kindleを買った

f:id:daikiojm:20170528202948j:plain

Kindleの本体代金分の本を買ったほうが得なんじゃないかという謎の衝動にかられ、ほしいものリストにある本を片っ端からカートにツッコミ、大体Kindle本体代金分ぐらいになったら発注するという謎のイベントを2,3回繰り返していた。
ただ、このイベントでは紙の書籍以外にもBDであったり、ガジェットのアクセサリ類なども同時に購入していたわけで、完全に意味の分からない状況になっていた。

今回は、母の日のギフトコードを使うと2300円OFFになるらしいので、過去の衝動買いイベントの反省も踏まえKindleを購入することにした。

選んだのは、このモデル。 f:id:daikiojm:20170528202958j:plain

機種と色は決まっていたものの、最終的に悩んだのが広告ありか広告なしかという点。
レビュー記事などを見ると、広告が表示されるのはトップ画面のみというのと、Amazonに関するAddが表示されるので、不快な広告がバンバン表示されることは無いらしいということがわかった。
Webページを見ている時にAddが表示されていても特に気にならない(よっぽど過剰でなければ)人なので、今回は広告ありモデルにした。
2000円の価格差がありその分浮いた気になって、ケーブル類を買ってしまった。

Kindel本体を手に入れたら手に入れたでKindle本を衝動買してしまっている…
結果的に読書が捗る気もするしよい気もする。

Hugoでブログを初めたけど結局はてなブログを使い始めた

案の定、ブログ始めましたポストです。

ブログを始めるにあたり、自分的に問題だったことを挙げてみる回です。 ※「◯◯問題」とか「◯◯おじさん」 みたいの大好きです。

どのブログサービス使うか問題

2017年にもなり、レンタルサーバーVPCを借りて自分でブログ用のCMSをインストールして使う… というのは、まず無いなぁとは思いつつも、「どのブログサービスで使うか」はブログ始める人にとっては割りと課題になるんじゃないかぁと

候補としては次のようなもの

ブログサービス系

手っ取り早く始めるならここらへんを使うのがいいだろうなぁという印象。 特にエンジニアの技術系ブログはダントツはてブロ率高し

ライトなブログ系

ここらへんもアカウント登録するだけで初められるし、Tumblrなんかはカスタムテーマも豊富 実はTumblrはやってました→ [link]

GitHubにホストする静的ページ系

  • DocPad
  • jekyll
  • Hugo

これらを何系とするのかは微妙なところだけど、勝手に一括りにさせてもらいました。

※ジャンル分けは適当です

結局は

HugoをGitHubホスティングすることに カスタマイズの自由度が高い点、内容をGitで管理できる点が大きかったです。 Hugoを選んだのはトレンド的にって言う部分と、Qiitaで参考になる記事が多く導入しやすそうだったから。 また、新しいサービスなんかが出てきたらそっちに移行するかもです。

↑とかゴチャゴチャ言っていましたが、結局はてなブログを使うことにしました。
一番の理由としては、更新するためにエディタターミナルGitHubを行き来しなければいかなかった点。
Hugoの制定気ファイル生成、公開用ブランチの切り替えなどをタスクランナーで自動化するなどすれば話は別なのかもしれないが、ブログ開設にそこまでの体力を避けなかったのも原因。
まずは、コンスタントに記事を書くことを第一に考えることにします。。。

書くこと無いよな問題

これが、今までにブログを始めてみようと思うも、結局やらないパターンになった主たる要因なきがする。
最近、ちょっとしたことでもQiitaにポストするというのを初めてみた。
これを初めてみると、自分の中でWebにアウトプットすることのハードルが少し下がったと感じることがある。
それと同時に、「Qiitaに投稿するべき内容ではないけど、自分のブログになら…」という内容を書きたいことがあった。 今なら!という思いもあり、今回再びブログを始めることに??

タイトル決まらない問題

こんなのどうでもよくて、とりあえず記事書けよ自分という話なのだが、これはかなり重大問題。
同じ理由でブログを始めるかどうか迷っている人は相当数いるはず。

今回は、GitHubページの1コンテンツとしてブログを埋め込む形をとったのでタイトルは必要なかった。
いずれ、ある程度記事が溜まってきたら、専用のドメインを取ってブログ部分だけを切り出そうかなぁとも思っている。
その時にはまた、"タイトル決まらない問題”に悩まされるわけだが…