python-social-authを0.1.xから0.2.xにアップデートする

## これは何？
[日本最大のチケット売買サービス「チケットキャンプ」](https://ticketcamp.net/)で使っている[python-social-auth](https://github.com/omab/python-social-auth)を0.1.xから0.2.13にアップデートした時の作業メモです。

前提として、Django 1.7.xと組み合わせて使っており、`social.apps.django_app.me`ではなく`social.apps.django_app.default`を利用しています。

## スキーマの変更
普通はDjangoの`manage.py migrate`を実行すればいいのでしょうが、諸々の事情でそれができないので、SQLを元にして変更点を確認します。

関連したテーブル一覧。

```
>SHOW TABLES LIKE 'social_auth_%';
+------------------------------------------+
| Tables_in_ticketcamp_dev (social_auth_%) |
+------------------------------------------+
| social_auth_association                  |
| social_auth_code                         |
| social_auth_nonce                        |
| social_auth_usersocialauth               |
+------------------------------------------+
```

現在使っている0.1.xのスキーマ。

```
CREATE TABLE `social_auth_association` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `server_url` varchar(255) NOT NULL,
  `handle` varchar(255) NOT NULL,
  `secret` varchar(255) NOT NULL,
  `issued` int(11) NOT NULL,
  `lifetime` int(11) NOT NULL,
  `assoc_type` varchar(64) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_code` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(75) NOT NULL,
  `code` varchar(32) NOT NULL,
  `verified` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`,`code`),
  KEY `social_auth_code_09bb5fb3` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_nonce` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `server_url` varchar(255) NOT NULL,
  `timestamp` int(11) NOT NULL,
  `salt` varchar(40) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_usersocialauth` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `provider` varchar(32) NOT NULL,
  `uid` varchar(255) NOT NULL,
  `extra_data` longtext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `provider` (`provider`,`uid`),
  KEY `social_auth_usersocialauth_6340c63c` (`user_id`),
  CONSTRAINT `user_id_refs_id_c8898d4c` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

最新版0.2.13のスキーマ。

```
CREATE TABLE `social_auth_association` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `server_url` varchar(255) NOT NULL,
  `handle` varchar(255) NOT NULL,
  `secret` varchar(255) NOT NULL,
  `issued` int(11) NOT NULL,
  `lifetime` int(11) NOT NULL,
  `assoc_type` varchar(64) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_code` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(254) NOT NULL,
  `code` varchar(32) NOT NULL,
  `verified` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `social_auth_code_email_801b2d02_uniq` (`email`,`code`),
  KEY `social_auth_code_c1336794` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_nonce` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `server_url` varchar(255) NOT NULL,
  `timestamp` int(11) NOT NULL,
  `salt` varchar(65) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `social_auth_nonce_server_url_f6284463_uniq` (`server_url`,`timestamp`,`salt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `social_auth_usersocialauth` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `provider` varchar(32) NOT NULL,
  `uid` varchar(255) NOT NULL,
  `extra_data` longtext NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `social_auth_usersocialauth_provider_e6b5e668_uniq` (`provider`,`uid`),
  KEY `social_auth_usersocialauth_user_id_17d28448_fk_auth_user_id` (`user_id`),
  CONSTRAINT `social_auth_usersocialauth_user_id_17d28448_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

インデックスのキーやカラムの順番の違いを除くと、

```
--- 0.1.sql     2015-12-12 06:36:39.164810101 +0000
+++ 0.2.sql     2015-12-12 06:36:18.612810595 +0000
@@ -11,7 +11,7 @@

 CREATE TABLE `social_auth_code` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `email` varchar(75) NOT NULL,
+  `email` varchar(254) NOT NULL,
   `code` varchar(32) NOT NULL,
   `verified` tinyint(1) NOT NULL,
   PRIMARY KEY (`id`),
@@ -23,8 +23,9 @@
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `server_url` varchar(255) NOT NULL,
   `timestamp` int(11) NOT NULL,
-  `salt` varchar(40) NOT NULL,
-  PRIMARY KEY (`id`)
+  `salt` varchar(65) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `social_auth_nonce_server_url_f6284463_uniq` (`server_url`,`timestamp`,`salt`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 CREATE TABLE `social_auth_usersocialauth` (
@@ -38,4 +39,3 @@
   KEY `social_auth_usersocialauth_6340c63c` (`user_id`),
   CONSTRAINT `user_id_refs_id_c8898d4c` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

- [Django 1.8での変更](https://docs.djangoproject.com/en/1.9/ref/models/fields/#emailfield)により`email`が最大254になっている。
- `python-social-auth`の[このIssue](https://github.com/omab/python-social-auth/issues/141)による変更により`salt`が最大65になっている。
- `python-social-auth`の[このIssue](https://github.com/omab/python-social-auth/issues/490)により`(server_url, timestamp, salt)`というユニーク制約がついている。

## 非互換な変更
### `BaseStrategy.backend`プロパティが消えた
0.2にバージョンアップした際に[`strategy`と`backend`の循環参照を回避するためのリファクタリングが入った](https://github.com/omab/python-social-auth/commit/7a21ae5626b73a6409f6f5c7ed58a1416adc55af#diff-edfca398eb84334baeba76ce424a2611)ので、pipelineの中で`strategy.backend`のように参照できなくなりました。

なので、

```py
from django.shortcuts import redirect
from social.pipeline.partial import partial

@partial
def my_pipeline(strategy, user=None, *args, **kwargs):
  if user:
      return

  return redirect('next_action', strategy.backend.name)
```

のようなコードを、

```py
from django.shortcuts import redirect
from social.pipeline.partial import partial

@partial
def my_pipeline(strategy, user=None, *args, **kwargs):
  if user:
      return

  backend = kwargs.get('backend')
  if not backend:
      return

  return redirect('next_action', backend.name)
```

のような感じに修正。

## 最後に
とりあえず0.2.13で会員登録・ログインが出来るところまで行きましたが、もう少しユニットテストを足さないと本番環境には怖くて出せないっす。