require 'rails_helper'

RSpec.describe "WebFinger", type: :request do
  describe "User does not exist" do
    it "returns a 404 status" do
      get "/.well-known/webfinger?resource=acct%3Ajane.doe%40kosmos.org"
      expect(response).to have_http_status(:not_found)
    end
  end

  context "User exists" do
    let(:user) { create :user, cn: 'tony', ou: 'kosmos.org' }

    before do
      allow_any_instance_of(User).to receive(:ldap_entry).and_return({
        uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
        services_enabled: ["mastodon", "remotestorage"]
      })
    end

    describe "Mastodon entries" do
      context "Mastodon available" do
        it "includes the Mastodon aliases and links for the user" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)

          expect(res["aliases"]).to include("http://example.social/@tony")
          expect(res["aliases"]).to include("http://example.social/users/tony")

          profile_link = res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}
          self_link    = res["links"].find{|l| l["rel"] == "self"}
          ostatus_link = res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}
          expect(profile_link["type"]).to eql("text/html")
          expect(profile_link["href"]).to eql("http://example.social/@tony")
          expect(self_link["type"]).to eql("application/activity+json")
          expect(self_link["href"]).to eql("http://example.social/users/tony")
          expect(ostatus_link["template"]).to eql("http://example.social/authorize_interaction?uri={uri}")
        end
      end

      context "Mastodon not enabled for user" do
        before do
          allow_any_instance_of(User).to receive(:ldap_entry).and_return({
            uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
            services_enabled: ["xmpp"]
          })
        end

        it "does not include Mastodon aliases or links" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)
          expect(res["aliases"]).not_to include("http://example.social/@tony")
          expect(res["aliases"]).not_to include("http://example.social/users/tony")
          expect(res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}).to be(nil)
          expect(res["links"].find{|l| l["rel"] == "self"}).to be(nil)
          expect(res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}).to be(nil)
        end
      end

      context "Mastodon not available" do
        before do
          Setting.mastodon_enabled = false
        end

        it "does not include Mastodon aliases or links" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)
          expect(res["aliases"]).not_to include("http://example.social/@tony")
          expect(res["aliases"]).not_to include("http://example.social/users/tony")
          expect(res["links"].find{|l| l["rel"] == "http://webfinger.net/rel/profile-page"}).to be(nil)
          expect(res["links"].find{|l| l["rel"] == "self"}).to be(nil)
          expect(res["links"].find{|l| l["rel"] == "http://ostatus.org/schema/1.0/subscribe"}).to be(nil)
        end
      end
    end

    describe "remoteStorage entries" do
      context "remoteStorage available" do
        it "includes the remoteStorage link for the user" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)
          rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"}

          expect(rs_link["href"]).to eql("#{Setting.rs_storage_url}/tony")

          oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"]
          expect(oauth_url).to eql("http://www.example.com/rs/oauth/tony")
        end
      end

      context "remoteStorage not enabled for user" do
        before do
          allow_any_instance_of(User).to receive(:ldap_entry).and_return({
            uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
            services_enabled: ["xmpp"]
          })
        end

        it "does not include the remoteStorage link" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)
          rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"}

          expect(rs_link).to be_nil
        end
      end

      context "remoteStorage not available" do
        before do
          Setting.remotestorage_enabled = false
        end

        it "does not include the remoteStorage link" do
          get "/.well-known/webfinger?resource=acct%3Atony%40kosmos.org"
          expect(response).to have_http_status(:ok)

          res = JSON.parse(response.body)
          rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"}

          expect(rs_link).to be_nil
        end
      end
    end
  end
end
