Bug(バグ) #2299
完了「紹介文を書かれたユーザーが招待したユーザー」が退会出来ない
100%
説明
Overview (現象)¶
「紹介文を書かれたユーザーが招待を出したユーザー」が退会動作を行うと500エラーが発生して退会できない。
また、退会動作は管理画面、ユーザー側どちらから行っても再現いたします。
同様に「紹介文を書かれたユーザーが出した招待」を削除しようとすると500エラーが発生する。
報告元¶
http://sns.openpne.jp/diary/26651
■現象 会員の退会/強制退会を実行すると、500エラーが発生して退会できない。 ■環境 OpenPNE 3.6 beta11 ■再現手順 1.会員Aが会員Bを招待する 2.会員Bで登録&ログインして、会員A向けにフレンド紹介文を作成する 3.会員Aが会員Cを招待する 4.会員Cで登録&ログインする 5.管理画面を開いて、「メンバー管理」から会員Cを強制退会する → 500エラー画面が表示される。 6.会員Cで自主退会しても同様に500エラーとなる Apacheのエラーログには以下のエラーメッセージが記録されます。 [Thu Jul 21 23:50:20 2011] [error] [client xxx.xxx.xxx.xxx] SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`beax`.`intro_friend`, CONSTRAINT `intro_friend_member_id_to_member_relationship_member_id_to` FOREIGN KEY (`member_id_to`) REFERENCES `member_relationship` (`member_id_to`)), referer: http://xxx.xxx.xxx.xxx/pc_backend.php/member/delete/id/3 ■原因(推測) intro_friendテーブルの以下の外部キー定義に問題があるように思います。 CONSTRAINT `intro_friend_member_id_to_member_relationship_member_id_to` FOREIGN KEY (`member_id_to`) REFERENCES `member_relationship` (`member_id_to`) 再現手順を行うと、以下のようなレコード構成になります。 memberテーブル ・レコード1:会員A ・レコード2:会員B ・レコード3:会員C member_relationshipテーブル ・レコード1:A <- B ・レコード2:B <- A ・レコード3:A <- C ・レコード4:C <- A intro_friendテーブルのレコード ・レコード1:A <- B 上記状態で会員Cを削除すると、以下のように削除に失敗します。 memberテーブルのレコード3削除する → DELETE ON CASCADE定義により、member_relationshipテーブルのレコード3と4が削除される → intro_friendテーブルの外部キー定義により、member_relationshipテーブルのレコード3の削除に失敗する(Aが外部キーとして参照されている)
再現バージョン¶
- OpenPNE3.6beta11
- beta12
- beta13
- opIntroFriendPlugin-0.9.2.1
再現手順¶
1. ユーザーBがフレンドのユーザーAの紹介文を書く
2. ユーザーAがユーザーCに招待メールを送る
3. ユーザーCでプロフィール登録を行う
4. 管理画面よりユーザーCを強制退会させる
5. 500エラーが出て退会できない
手順3を行わず、手順2で送信した招待を取り消そうとしても500エラーが発生する
Causes (原因)¶
バグが発生した原因を記入
Way to fix (修正内容)¶
修正内容を記入
Minoru Takai さんが約13年前に更新
問題の再現を確認しました。
(OpenPNE, opIntroFriendPlugin) = (3.6beta10, 0.9.1.2), (3.6beta11, 0.9.2.1), (3.6beta12, 0.9.2.1), (3.6beta13, 0.9.2.1) で再現を確認できています。おそらく全てのバージョンの opIntroFriendPlugin で生じる問題です。
調査¶
- A <=> B : フレンドになる:紹介文を書くため
- B => A : 紹介文がある(B から A に書く)
- A <=> C : member_relationship レコードあり(フレンド)
- A => D : member_relationship レコードあり(A が D を招待中)
- A <= E : member_relationship レコードあり(E が A にフレンド申請中)
- A <=> F : member_relationship レコードあり(一度フレンドになり、その後フレンドを解消した)
この状態で C, D, E, F のメンバーを削除しようとすると、次のエラーが生じます。
削除操作は、 (C, E, F) は、そのメンバー自身で退会操作をするか、管理画面からの強制退会操作をする場合であり、 (D) は、招待者が「招待中メールアドレス一覧」から削除操作をする場合が考えられる。
500 | Internal Server Error | Doctrine_Connection_Mysql_Exception SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`DB_NAME/intro_friend`, CONSTRAINT `intro_friend_member_id_to_member_relationship_member_id_to` FOREIGN KEY (`member_id_to`) REFERENCES `member_relationship` (`member_id_to`))
なお、この例では B を削除することは可能です(B が紹介文を書いているかどうかではなく、B 以外の誰も紹介文を書いていないことが必要です)。
つまり、
- メンバー削除したいメンバーを X とする
- あるメンバー A が、 X 以外から紹介文を書かれている
- そのメンバー A と X の間に member_relationship レコードが存在する(少なくとも次の (1) 〜 (4) のいずれかが考えられる)
- (1) A <=> X : フレンド
- (2) A => X : A が X を招待中
- (3) A <= X : X が A にフレンド申請中
- フレンド申請を取り消す方法は用意されていないらしい
- (4) A <=> X : 一度フレンドになり、その後フレンドを解消した
- このとき、 X を退会操作すると 500 エラーとなる
- dev モードではなく prod モードの場合は、次のメッセージが表示される
現在、サーバが混み合っているか、メンテナンス中です。 ご迷惑をおかけいたしますが、しばらく時間を空けて再度アクセスしてください。 Currently, our service is too busy or is under maintenance. We're sorry and please retry accessing later.
- dev モードではなく prod モードの場合は、次のメッセージが表示される
という問題です。
追記: member_relationship レコードができるタイミングとして、「(5) 相手をアクセスブロックした」というのもありそうですね。
Shingo Yamada さんが約13年前に更新
- ステータス を New(新規) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
確認中にします。
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 対象バージョン を v1.0.0 にセット
- 進捗率 を 50 から 70 に変更
スキーマ定義の変更が入ってしまっていますが、やむを得ないと判断して取り込みました(安定版には opIntroFriendPlugin はバンドルされておらず、この変更については特に影響ないものと思われます)。
Yuma Sakata さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更
テストOKです。