【Rails】自作WebアプリからAPIを叩いてMastodonアカウント作成
表題について個人開発のWebアプリ「まちかどルート」v5.3への実装メモ。プログラミングに入門して8ヶ月弱。Mastodonのアカウント作成APIに挑戦してみました。
MastodonとのOauth連携について
まちかどルートでは開発スタート当初からSNS「Mastodon」のアカウントでログイン認証できるようにしてあります。
MastodonとのOauth連携についてここでは詳しく書きません。
たとえばこちらの記事などを参考にしています。
RailsなサービスでMastodonとのOauth連携を実装する
https://qiita.com/foloinfo/items/48389328da43d73ae7a0
アカウント作成用のAPIが用意された
今回の実装に至ったきっかけは、Mastodonのv2.7.0からアカウント作成用のAPIが追加されたことでした。さらにmastodon-api v2.0.0というgemにもMastodon::REST::Client#create_account
が追加されたんです。
これらによって自作のWebアプリからの新規アカウント作成プロセスをかなり簡略化できるのではないかと思い、「よしやってみよう」となりました。
なお、APIに関するドキュメントはこちらにあります。
view : アカウント作成フォーム
<p>新規アカウント登録</p>
<%= form_with url: '/auth/create/account', method: :post, local: true do |f| %>
<input type="text" name="username" placeholder="ユーザー名(英数字&空白なし)">
<input type="email" name="email" placeholder="メールアドレス">
<input type="password" name="password" placeholder="パスワード">
<input type="hidden" name="agreement" value="true">
<input type="hidden" name="locale" value="ja">
<%= button_tag :type => "submit", data: { disable_with: "登録中..." } do %>
<span>登録</span>
<% end %>
<% end %>
<p>新規アカウント登録</p>
<%= form_with url: '/auth/create/account', method: :post, local: true do |f| %>
<input type="text" name="username" placeholder="ユーザー名(英数字&空白なし)">
<input type="email" name="email" placeholder="メールアドレス">
<input type="password" name="password" placeholder="パスワード">
<input type="hidden" name="agreement" value="true">
<input type="hidden" name="locale" value="ja">
<%= button_tag :type => "submit", data: { disable_with: "登録中..." } do %>
<span>登録</span>
<% end %>
<% end %>
前述のドキュメントにあるとおり、Mastodonのアカウント作成ではusername
email
password
agreement
locale
という5つのパラメータが必要なので、それらの入力フォームを作ります。
agreement
のデータ型はBooleanなのでここでは true
としてあります。たとえば「利用規約に同意する」といったチェックボックスを用意し、ユーザーが同意してチェックしたら true
にする、という用途に使えるんでしょうね。
controller : sessions_controller.rb
/app/controllers/sessions_controller.rb
def create
if params[:username] # ここで新規アカウント作成or通常のログインかを判断
# APIを叩くときに必要となるMastodonインスタンスの管理者情報を抽出
# ここでは私が管理しているMastodonインスタンス「アナザーギルド」を例にしています
@mastodon_master = User.where(uid: '[email protected]').order(created_at: :desc).first
# アカウント作成フォームで入力された5つのパラメータを格納
username = params[:username]
email = params[:email]
password = params[:password]
agreement = params[:agreement]
locale = params[:locale]
# 5つのパラメータをparamsにハッシュとして格納
params = { "username" => username, "email" => email, "password" => password, "agreement" => agreement, "locale" => locale }
# APIを叩けるようにするためのclient生成
client = Mastodon::REST::Client.new(base_url: "https://another-guild.com", bearer_token: @mastodon_master.token)
# すでに登録済みのアカウントかどうかを判断するための例外処理 begin~rescue
begin
# ここでアカウント作成APIを叩きます
@new_user = client.create_account(params)
rescue => e
flash[:error] = "登録できませんでした。ユーザー名またはメールアドレスはすでに存在します"
redirect_to root_path
return
end
# アカウントが無事に作成されたらuserモデルに新規レコード作成&保存
uid = username + '@another-guild.com'
@user = User.find_or_create_by(uid: uid) do |user|
user.provider = 'mastodon'
user.token = @new_user.access_token
end
flash[:notice] = "登録したメールアドレスにメールが届きます。確認のうえ、まちかどルートにログインしてください"
end
end
ルーティング : routes.rb
/config/routes.rb
post "/auth/create/account" => "sessions#create"
def create
if params[:username] # ここで新規アカウント作成or通常のログインかを判断
# APIを叩くときに必要となるMastodonインスタンスの管理者情報を抽出
# ここでは私が管理しているMastodonインスタンス「アナザーギルド」を例にしています
@mastodon_master = User.where(uid: '[email protected]').order(created_at: :desc).first
# アカウント作成フォームで入力された5つのパラメータを格納
username = params[:username]
email = params[:email]
password = params[:password]
agreement = params[:agreement]
locale = params[:locale]
# 5つのパラメータをparamsにハッシュとして格納
params = { "username" => username, "email" => email, "password" => password, "agreement" => agreement, "locale" => locale }
# APIを叩けるようにするためのclient生成
client = Mastodon::REST::Client.new(base_url: "https://another-guild.com", bearer_token: @mastodon_master.token)
# すでに登録済みのアカウントかどうかを判断するための例外処理 begin~rescue
begin
# ここでアカウント作成APIを叩きます
@new_user = client.create_account(params)
rescue => e
flash[:error] = "登録できませんでした。ユーザー名またはメールアドレスはすでに存在します"
redirect_to root_path
return
end
# アカウントが無事に作成されたらuserモデルに新規レコード作成&保存
uid = username + '@another-guild.com'
@user = User.find_or_create_by(uid: uid) do |user|
user.provider = 'mastodon'
user.token = @new_user.access_token
end
flash[:notice] = "登録したメールアドレスにメールが届きます。確認のうえ、まちかどルートにログインしてください"
end
end
post "/auth/create/account" => "sessions#create"
アカウント作成フォームから sessions_controller.rb
の create
に誘導するためのルーティングとしてこの1行を追記します。
Rack Middlewareへの例外処理
以上のように書くと簡単なようですけど、じぶんにとっては難題でした。それに拍車をかけるように大きな壁が...。というのもアカウント作成までうまくいき、Mastodonから確認メールが送られてくるのですが
確認メールにある「確認し まちかどルート に戻る」ボタンを押すと
NoMethodError (undefined method `split' for nil:NilClass):
omniauth-mastodon (0.9.3) lib/omniauth/strategies/mastodon.rb:82:in `set_options_from_identifier'
omniauth-mastodon (0.9.3) lib/omniauth/strategies/mastodon.rb:41:in `callback_phase'
...
というエラーが出てしまったんです。
いろいろ調べたりしたのですがスキル不足でどうにもならず、無理やり下記のような対策をしました。
具体的には、今回のケースではRailsのcontrollerで起きた問題ではなくgemのomniauth-mastodonつまりRack middlewareで発生した例外であるため exceptions_app
というものを利用しました。
Rails.application.configure do
config.exceptions_app = self.routes
end
class ErrorsController < ActionController::Base
def not_found
redirect_to root_path
end
end
get '500', to: 'errors#not_found'
あとがき
最後の例外処理があまりにも無理やりな感じがして、なんともしまらないメモになってしまいました。まだまだ未熟なのでこれからも学びつづけながらアウトプットしていきます。
余談ですが
Mastodonインスタンスの管理ページにある「サイト設定」で「新規登録を受け付ける」にチェックが入っていないと下記のエラーが発生してアカウント作成APIを受け付けません。
Mastodon::Error::Forbidden (Mastodon::Error::Forbidden):
これに気づくだけでも時間を要してしまいました。
けれど自作のWebアプリからの新規アカウント作成プロセスを簡略化したい!という目的はある程度まで達成できたと思います。TwitterやFacebookとかと違って(ないですよね?)アカウント作成APIまで用意しているMastodon。今後も期待しつつそのほかのAPIにも機会があったらまた挑戦したいです。
Author And Source
この問題について(【Rails】自作WebアプリからAPIを叩いてMastodonアカウント作成), 我々は、より多くの情報をここで見つけました https://qiita.com/west2538/items/cd1ea7a0bc0a70c617f6著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .