AWSでCSRを作成する

AWSサーバに入るための鍵がppkという拡張子になっている。下記を見ながら変更してみる。
Putty の鍵ファイル .ppk を Linux ssh 用に変換してみる

yumが使えないから、下記を見ながらやってみる。
Run Putty on Mac OS X 10.6.8

sudo port install puttyってやっても、下記のエラーになった。
Error: Processing of port putty failed

sudo port selfupdateでportをアップデートしてみた。
テザリングでやってるから超おそい。
そもそもputtyとはなにか?

Windows OSで稼働するSSHクライアント。TTSSHとは異なり,SSHプロトコルversion2にも対応している。さらに,ファイル転送のためのscpや公開鍵認証のためのagentなど,UNIX版SSHクライアントの機能を多数サポートしている。

これがMacでも使えるらしい。SSHクライアントなんていらないんだけどな。やっぱり変換したい。
それにしてもUpdating the ports treeから動かない。諦めるか。一回とめてもう一回やってみる。やっぱり動かない。

そもそも変換したいわけだから、Putty自体は不要だし、どうもputtygenというのがあればいいらしい。
MacでPutty形式の秘密鍵を変換するこれみてもう一度やってみる。
brew install putty
おお出来たっぽい。

ppkを下記で変換できた。

puttygen putty_key.ppk -O private-openssh -o ~/.ssh/from_putty_key_rsa

SSHで接続しようとしてもPermission denied (publickey).ってでてエラーになる!
おーできた。ユーザ名指定してなかった笑

■CSRの作成(ジオトラスト)
サーバー証明書の作成、アップロード、削除
CSRの生成方法

CSRとは?企業の社会的責任ではない。CSRとは、お客様が生成し、認証局に提出する署名リクエスト(Certificate Signing Request)です。

ここで一旦お昼ご飯にする。

LESS

CSSをシンプルに書くことができるLESS使ってみた
Twitter Bootstrapを使ったサイト構築の流れ (後編)

便利だの。twitter bootstrap3というのは、昔のbootstrapと結構違いますね。LESSというのを使っているので、勉強してみようと思いました。LESSというのはCSSの値をパッケージングできまっす。なのでbootstrapのややこしいcssも簡単にカスタマイズできるようになっているのかもしれません。

http://incident57.com/less/

これがMac用のLessコンパイラーというやつらしいです。Lessを作ってコンパイラーでCssにするそうです。twitter bootstrapは全部Lessでcssを管理しており、bootstrapのgithubにそのLessがあります。これをカスタマイズしてコンパイラーでcssにして、bootstrapのcssを入れ替えればいいそうです。

ただ、どうも、上記コンパイラだとエラーがでる。&:extend(.clearfix all)というやつに対応できていないっぽい。有料版の下記だと問題なくコンパイルできました。

http://incident57.com/codekit/

下記のようにネストもできるようです。関数的なこともできるし、計算もできるようです。いいっすね。

@bgcolor: #09c;
@brand_color: red;

div#hoge .hoge table{
    color: black;
    background-color: @bgcolor;
    
    th{
        color: @brand_color;
    }
}

LESSと同じようなメタ言語として、Sass、Stylusなどがあるらしい。聞いたことはある。

管理画面のメニューを自動で作成する

管理者の権限は色々ありますし、最終的にはメソッド単位で細かく管理できないといけないと思います。
あと、単にそのメソッドを実行できるか否かだけではなく、どのデータを扱うことができるかまで管理できる必要があります。
こういうのはどうもACLというらしいです。

すごく基本的な管理者権限を考えると、管理者のグループを作成して、そのグループがどのモデルに属するかを設定するといいのではないかと思いました。例外処理ができないと実用的ではありませんが、グループがモデルに属するのであれば、アソシエーションの状態から、自動的に実行可能なメソッドと、編集可能なデータを決定できるのではないかと思います。

例えば、roleのグループをrolesというテーブルで管理しつつ、その各グループに属するモデルもデータベース上で設定しておきます。role_idが1のグループは、Shopモデルに属するのであれば、Shopが持っているHasOneとかHasManyとかのテーブルのみ管理できるようにすればよいです。ShopがMovieを持っている場合、Movieのadmin_index,admin_view,admin_edit,admin_deleteへのアクセスが許可されて、admin_indexは自分が持っているMovieのみ表示されるといった感じになります。これをコンポーネント化しておけば、beforeFileterとかで$this->Auth->user(‘role_id’)をチェックして自動的に埋め込みが可能なんではないだろうかと思いました。

cakePHPのプロジェクトを簡単に作成するようにする

cakePHPをやってる人なら少なからずやってると思いますが、僕はやってません。
今考えて仕組みをつくりたいと思います。

今つくっているBakeを使いたいので、BakeのプロジェクトをGithubのリポジトリに入れておいて、それをクローンしてデータベースをつくって、Bakeします。すると作成したいサイトの大方(まだ少し)が出来上がるので、それを別のブランチとしてpushします。で納品時にBakeプラグインなどを簡単に削除できるコマンドを用意しておき、それを実行します。

というのでどうでしょうか?
まあシークレット文字列とかは手動変更が必要だなこれじゃあ。まあ今はいいか。

Bake お気に入り登録機能

お気に入りの登録機能を実装するときにどうしようかなと思っております。
単純に考えると、お気に入りを登録する対象を設定しておき、その対象設定に基づき、モデルを作成します。もしテーブルがなければモデル作成の前にテーブル作成してもいいです。

例えばshopsにお気に入りを登録するという設定がされている場合、shop_likesテーブルを作成して、ShopLikeモデルを作成するわけです。でもshopsにlike_countみたいなお気に入り数を登録したい場合もあるでしょうから、shopsが対象に設定されているのに、like_countがフィールドとしてつくられていない場合は、それも事前に作成してもよいと思います。

しかしながらそうなると、モデル作成関数の実行前にこれら全てを実行する必要がありますので、テーブル作成関数というモデル作成の前段のフェーズをもう少しきちんと考えた方がいいのかなとも思う訳です。おまけにいうと、僕は今Bakeの設定のためのデータベースと、Bakeによって作成するデータベースを同じにしてしまっております。これを分けること自体はもちろん可能だと思うのですが、どうも頭の中でこの2つが混在しているようです。つまりいざ分けようとするときに、あらわけられないじゃんこれじゃあという風になるだろうと思っている訳です。

本来であればというか理想としてはBakeのための設定情報データベースのみから、Bakeにより作成するテーブルを全て新規で作成し、
それに基づきモデルを作成し、、、という流れであれば一番分かりやすいわけです。しかしながら、それはそれで大変でありますし、phpmyadiminを使えばデータベースの作成というのは割とすぐにできるものであり(簡単なものならですが)ますので、そのテーブル情報に基づきBakeするという考え方は、踏襲してもいいのではないかと思っております。

なので、最終的に納品するような状態になった場合に限り、設定情報に関連するテーブルを削除するという考え方で進めればいいのだなと今思いました。となるとまあ今のまま進めていいのか。

defaultデータベースにお気に入り設定に関するテーブルを作成しまして、そこに対象となるモデルを登録するようにします。
Bakeの前段でテーブル作成関数を実行して、そこでお気に入りに関する未作成のテーブルを作成するようにします。
となると、画像登録(Filebinder)に関する未作成テーブルもそこで作成することになります。なにしろ、機能毎に別個でテーブル、モデル、コントローラー。。。という風に作成していくと、不整合が生じてしまいますので、テーブル、モデル、コント、、という流れの中で全機能をつつがなく実装していく必要があるわけであります。

Bake改造 あたまの整理

Bakeを改造しているわけですが、結局何がしたいのか不明瞭なままつくっているとたこ足配線みたいになってきますので、目的をしぼってリファクタリングしていきます。最終的にはWEB上で設定した内容に基づいてぽこっとサイトを生むようなものを想定しておりますので、Bakeのコンソール上で設定を入力させるような機能はいらないわけで、むしろサイトの設定内容に基づき一から完全なサイトを瞬間的に一気に作成することが必要なわけですから、どの設定をいじっても確実のその設定が反映されたサイトが自動作成されるようにする必要があり、裏側のBakeコマンドは1つでいいわけです。その一つに全てを集約させていきます。

データベースがあり、そこに設定情報があります。その設定情報に基づき、モデルを作成し、コントローラーを作成し、ビューを作成します。認証情報にソーシャルを連動させるか否か、お気に入り機能を搭載するか否か、各モデルにおいて画像を登録させるか否かなどの情報はモデル作成段階、コントローラー作成段階、ビュー作成段階でそれぞれチェックし、設定内容に応じたモデル、コントローラー、ビューを作成していく必要があります。

あと最終的には、特定のディレクトリに新しいプロジェクトを作成し、シークレット文字列?とかもランダムに変えつつ、今回作成するBakeプラグインなどを排除したものにし、データベースからも設定情報自体は削除(分離)するようにしたいです。自動作成するための情報は、自動作成後(納品後)は基本不要だからであります。まあこの辺りは特段問題ないですので、後で考えるとして、やはり設定情報を全てDB上で表現できるようにし、その情報に基づいてターミナルからBakeすることで一発サイト作成が出来る状態を早々につくっていきたいと思います。

cakePHP2.3 Bakeの改造

coreのbakeをコピーしてプラグイン化することによりオリジナルbakeを作成します。

bakeに、下記機能を追加していきます。
・twitter bootstrapを使ったviewに変更する
・多言語化機能を使った効率的な日本語化を可能にする
・管理画面のメニューもDBに応じて自動作成する
・認証関連も自動実装する
・問い合わせ機能も自動実装する
・userの権限に応じた細かなアクセス管理(表示・編集内容の限定)を自動実装する
・ユーザのマイページのメニューも自動作成する
・お気に入り、口コミ機能なども自動実装を可能にする
・ソーシャル連動も自動実装する
・サイト名、各ページのMETA情報の登録などの管理画面も自動作成する
・デザインはTempleteの入れ替えで柔軟に変更できるものにする
・画面構成などは順次パターンを増加させて、なるべく柔軟な画面構成、遷移、デザインへの対応を実現していく
・上記の機能をWEB上で設定〜サイト自動作成までを可能にする
・本システムを利用するユーザ毎に作成したサイトの一覧などを保存できるようにする
・主要サイトパターン毎に個別の設定画面を儲けてより的を得たサイトを簡単に自動作成できるようにする

cakePHP プラグイン内でモデルを使う

プラグインを追加して、プラグインのコントローラーから、プラグインではないモデルにアクセスする方法がよく分からない。
というか、User認証に関するロジックをプラグイン化しつつ、モデルは既存のUserモデルを使おうとするときに、プラグインのユーザ登録画面で、Userモデルに記載しているバリデーションがなぜか中途半端に機能しない。notemptyは機能するが、それ以外のvalidationロジックがまったくきかない。なぜだ??確かにプラグインの各種連動の仕組みをしっかり分かっていない。だから変なことになっているのかもしれない。

プラグイン内のコントローラー名は、UserControllerにしていたのだが、これだとどうもうまくいかないらしい。
HogeUserControllerにして、public $uses = array(‘User);としつつ、$this->User->save($this->request->data)とするとうまくバリデーションが効いた。中途半端に効くというのは一番困るわー。

cakePHP2.3 多言語化

app/Consoleに移動して、下記を起動する

./cake i18n

E押したら翻訳ファイルみたいのを作ってくれる。詳細は、ここ。わかりやすい。

/app/Locale/jpn/LC_MESSAGES/default.poに出力したファイルをコピーする。僕の場合は、/app/Locale内にdefault.potというファイルが出来たので、それを上記パスにdefault.poとしてコピーした。potをpoにするのが重要でありんす。そのpoファイルに英語に対応する日本語をせこせこ記述すると、日本語訳してくれるようになった。

AppControllerとかで、beforefilterに下記のように書くと環境に関わらず強制的に言語を変更できる。日本の場合は、ja。

function beforeFilter() {
	Configure::write('Config.language', 'en');
}

githubにpushするとcapistranoと連動して自動デプロイする

githubにはPost-Receive Hooksという機能があり、これはpushされると、登録したurlにpostアクセスし、json形式でpushしたデータの内容を渡してくれる。なので、このgithubからのpostアクセスを受け付けて、pushデータ内容に応じて、capistranoのサーバにアクセスしcapistranoでデプロイをするようにすれば、pushからの自動デプロイが可能になる。

PHPでGitHubからのpostアクセスの受けをつくる

今回はcapistranoと同じサーバにGitHubのpostアクセスの受けをつくった。ちなみにさくらのvpsサーバ。
apacheの設定をしてgithubから受けられるようにする。受けのphpは下記のような感じにした。

<?php
if(! isset($_POST['payload'])) die();

$payload = json_decode($_POST['payload']);
if(! (isset($payload->repository->url) && $payload->repository->url == 'https://github.com/hogehoge')){
    die();
}

chdir('../cap/hoge');
shell_exec('cap dev deploy');

githubから来てるものに限定するとかするともっとよい。あと、ブランチに応じて、開発サーバデプロイと、本番サーバデプロイを分けるとかできる。まあでも本番デプロイは手動でもいいか。さくらvpsだとapacheのドキュメントルートは/var/www/htmlでして、そこに上記phpファイルを置いております。chdirはつまり/var/www/cap/hogeに移動しており、hoge上にcapistranoフォルダを作っており、そこでcap dev deployをしております。githubのpostアクセスを受けているのはapacheですので、cap dev deployしているのもapacheになります。なので、apache君のssh pubkeyを作ったりしました。あとデプロイサーバのssh pubkeyもgithubに登録しました。僕のcapistranoはどこかで調べてconfig/deploy.rb以外に、config/deploy/dev.rbというのもありますので、それぞれ下記のような内容にしました。ちなみにデプロイサーバもサクラのレンタルサーバです。

config/deploy.rb

require "capistrano/ext/multistage"
require "capistrano_colors"
require "railsless-deploy"
require "rubygems"

ssh_options[:forward_agent] = false
set :normalize_asset_timestamps, false
set :use_sudo, false
default_run_options[:pty]   = true

#ステージ
set :stages, ["dev", "pro"]
set :default_stage, "dev"
# バージョン管理
set :scm, :git
set :scm_passphrase, "hogehogehoge"
# リポジトリ
set :repository, "git@github.com:hogeo/hoge.git"
# ブランチ
set :branch, "dev"
# デプロイ方式
#set :deploy_via, :remote_cache
#世代管理
set :keep_releases, 1 

# デプロイ対象外ファイル
set :copy_exclude, [".git", ".gitignore"]

config/deploy/dev.rb

# アプリケーション名
set :application, "hoge"
# デプロイ先ディレクトリ
set :deploy_to, "/home/hogeo/www/#{application}"

# デプロイサーバー
role :web, "hogeo@hogeo.sakura.ne.jp"
role :app, "hogeo@hogeo.sakura.ne.jp"

#ユーザアカウント
set:user, "hogeo"
set:password, "hogehogehoge"

set :scm_passphrase, "hogehoge"

namespace :deploy do
  before "deploy" do
    try_sudo "chown -R hogeo:users #{deploy_to}"
  end
end

after "deploy", "upload_config"

desc "各種セットアップ情報をアップロードします"
task :upload_config, roles => :web do
 run "cp -f /home/hogeo/www/hoge/database.php #{latest_release}/app/Config/."
 run "chmod -R 755 #{deploy_to}/current/"
 run "rm -rf #{latest_release}/app/tmp/cache/persistent/*"
 run "rm -rf #{latest_release}/app/tmp/cache/models/*"
 run "rm -rf #{latest_release}/app/tmp/logs/*"
end

参考
Webサイトをgithubで管理してpush時に自動的に同期する方法
GitHubとJenkins連動 自動デプロイ 開発環境設定編
githubにPushしたらwebhooksとSinatraを利用してサイトを自動的に更新する
GithubにあるプライベートリポジトリをCapistranoでデプロイ