From 172eaeba3fd217228dead279712aecce8c3ac080 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Mon, 23 Sep 2019 22:37:45 +0900 Subject: Add config of multipart threshold for S3 (#11924) --- config/initializers/paperclip.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'config/initializers') diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index ce4185e02..cfc95330c 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -25,6 +25,7 @@ if ENV['S3_ENABLED'] == 'true' s3_protocol: s3_protocol, s3_host_name: s3_hostname, s3_headers: { + 'X-Amz-Multipart-Threshold' => ENV.fetch('S3_MULTIPART_THRESHOLD') { 15.megabytes }, 'Cache-Control' => 'public, max-age=315576000, immutable', }, s3_permissions: ENV.fetch('S3_PERMISSION') { 'public-read' }, -- cgit From a1f04c1e3497e9dff5970038461d9f454f2650df Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 24 Sep 2019 04:35:36 +0200 Subject: Fix authentication before 2FA challenge (#11943) Regression from #11831 --- app/controllers/auth/sessions_controller.rb | 61 +++++++++++++++------------ app/models/concerns/ldap_authenticable.rb | 44 +++++++++++++++---- config/application.rb | 3 +- config/initializers/devise.rb | 11 ++--- lib/devise/ldap_authenticatable.rb | 55 ------------------------ lib/devise/two_factor_ldap_authenticatable.rb | 32 ++++++++++++++ lib/devise/two_factor_pam_authenticatable.rb | 31 ++++++++++++++ 7 files changed, 139 insertions(+), 98 deletions(-) delete mode 100644 lib/devise/ldap_authenticatable.rb create mode 100644 lib/devise/two_factor_ldap_authenticatable.rb create mode 100644 lib/devise/two_factor_pam_authenticatable.rb (limited to 'config/initializers') diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index b3113bbef..f48b17c79 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -8,6 +8,8 @@ class Auth::SessionsController < Devise::SessionsController skip_before_action :require_no_authentication, only: [:create] skip_before_action :require_functional! + prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] + before_action :set_instance_presenter, only: [:new] before_action :set_body_classes @@ -20,22 +22,9 @@ class Auth::SessionsController < Devise::SessionsController end def create - self.resource = begin - if user_params[:email].blank? && session[:otp_user_id].present? - User.find(session[:otp_user_id]) - else - warden.authenticate!(auth_options) - end - end - - if resource.otp_required_for_login? - if user_params[:otp_attempt].present? && session[:otp_user_id].present? - authenticate_with_two_factor_via_otp(resource) - else - prompt_for_two_factor(resource) - end - else - authenticate_and_respond(resource) + super do |resource| + remember_me(resource) + flash.delete(:notice) end end @@ -49,6 +38,16 @@ class Auth::SessionsController < Devise::SessionsController protected + def find_user + if session[:otp_user_id] + User.find(session[:otp_user_id]) + else + user = User.authenticate_with_ldap(user_params) if Devise.ldap_authentication + user ||= User.authenticate_with_pam(user_params) if Devise.pam_authentication + user ||= User.find_for_authentication(email: user_params[:email]) + end + end + def user_params params.require(:user).permit(:email, :password, :otp_attempt) end @@ -71,6 +70,10 @@ class Auth::SessionsController < Devise::SessionsController super end + def two_factor_enabled? + find_user&.otp_required_for_login? + end + def valid_otp_attempt?(user) user.validate_and_consume_otp!(user_params[:otp_attempt]) || user.invalidate_otp_backup_code!(user_params[:otp_attempt]) @@ -78,10 +81,24 @@ class Auth::SessionsController < Devise::SessionsController false end + def authenticate_with_two_factor + user = self.resource = find_user + + if user_params[:otp_attempt].present? && session[:otp_user_id] + authenticate_with_two_factor_via_otp(user) + elsif user.present? && (user.encrypted_password.blank? || user.valid_password?(user_params[:password])) + # If encrypted_password is blank, we got the user from LDAP or PAM, + # so credentials are already valid + + prompt_for_two_factor(user) + end + end + def authenticate_with_two_factor_via_otp(user) if valid_otp_attempt?(user) session.delete(:otp_user_id) - authenticate_and_respond(user) + remember_me(user) + sign_in(user) else flash.now[:alert] = I18n.t('users.invalid_otp_token') prompt_for_two_factor(user) @@ -90,16 +107,10 @@ class Auth::SessionsController < Devise::SessionsController def prompt_for_two_factor(user) session[:otp_user_id] = user.id + @body_classes = 'lighter' render :two_factor end - def authenticate_and_respond(user) - sign_in(user) - remember_me(user) - - respond_with user, location: after_sign_in_path_for(user) - end - private def set_instance_presenter @@ -112,11 +123,9 @@ class Auth::SessionsController < Devise::SessionsController def home_paths(resource) paths = [about_path] - if single_user_mode? && resource.is_a?(User) paths << short_account_path(username: resource.account) end - paths end diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/ldap_authenticable.rb index 84ff84c4b..117993947 100644 --- a/app/models/concerns/ldap_authenticable.rb +++ b/app/models/concerns/ldap_authenticable.rb @@ -3,24 +3,50 @@ module LdapAuthenticable extend ActiveSupport::Concern - def ldap_setup(_attributes) - self.confirmed_at = Time.now.utc - self.admin = false - self.external = true + class_methods do + def authenticate_with_ldap(params = {}) + ldap = Net::LDAP.new(ldap_options) + filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, email: params[:email]) - save! - end + if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: filter, password: params[:password])) + ldap_get_user(user_info.first) + end + end - class_methods do def ldap_get_user(attributes = {}) resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first }) if resource.blank? - resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }) - resource.ldap_setup(attributes) + resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }, admin: false, external: true, confirmed_at: Time.now.utc) + resource.save! end resource end + + def ldap_options + opts = { + host: Devise.ldap_host, + port: Devise.ldap_port, + base: Devise.ldap_base, + + auth: { + method: :simple, + username: Devise.ldap_bind_dn, + password: Devise.ldap_password, + }, + + connect_timeout: 10, + } + + if [:simple_tls, :start_tls].include?(Devise.ldap_method) + opts[:encryption] = { + method: Devise.ldap_method, + tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.tap { |options| options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Devise.ldap_tls_no_verify }, + } + end + + opts + end end end diff --git a/config/application.rb b/config/application.rb index 5fd37120d..3ced81b8f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -13,7 +13,8 @@ require_relative '../lib/paperclip/video_transcoder' require_relative '../lib/paperclip/type_corrector' require_relative '../lib/mastodon/snowflake' require_relative '../lib/mastodon/version' -require_relative '../lib/devise/ldap_authenticatable' +require_relative '../lib/devise/two_factor_ldap_authenticatable' +require_relative '../lib/devise/two_factor_pam_authenticatable' Dotenv::Railtie.load diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 311583820..fd9a5a8b9 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -71,13 +71,10 @@ end Devise.setup do |config| config.warden do |manager| - manager.default_strategies(scope: :user).unshift :database_authenticatable - manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_authentication - manager.default_strategies(scope: :user).unshift :pam_authenticatable if Devise.pam_authentication - - # We handle 2FA in our own sessions controller so this gets in the way - manager.default_strategies(scope: :user).delete :two_factor_backupable - manager.default_strategies(scope: :user).delete :two_factor_authenticatable + manager.default_strategies(scope: :user).unshift :two_factor_ldap_authenticatable if Devise.ldap_authentication + manager.default_strategies(scope: :user).unshift :two_factor_pam_authenticatable if Devise.pam_authentication + manager.default_strategies(scope: :user).unshift :two_factor_authenticatable + manager.default_strategies(scope: :user).unshift :two_factor_backupable end # The secret key used by Devise. Devise uses this key to generate diff --git a/lib/devise/ldap_authenticatable.rb b/lib/devise/ldap_authenticatable.rb deleted file mode 100644 index 6903d468d..000000000 --- a/lib/devise/ldap_authenticatable.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -require 'net/ldap' -require 'devise/strategies/authenticatable' - -module Devise - module Strategies - class LdapAuthenticatable < Authenticatable - def authenticate! - if params[:user] - ldap = Net::LDAP.new( - host: Devise.ldap_host, - port: Devise.ldap_port, - base: Devise.ldap_base, - encryption: { - method: Devise.ldap_method, - tls_options: tls_options, - }, - auth: { - method: :simple, - username: Devise.ldap_bind_dn, - password: Devise.ldap_password, - }, - connect_timeout: 10 - ) - - filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, email: email) - - if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: filter, password: password)) - user = User.ldap_get_user(user_info.first) - success!(user) - else - return fail(:invalid) - end - end - end - - def email - params[:user][:email] - end - - def password - params[:user][:password] - end - - def tls_options - OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.tap do |options| - options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Devise.ldap_tls_no_verify - end - end - end - end -end - -Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) diff --git a/lib/devise/two_factor_ldap_authenticatable.rb b/lib/devise/two_factor_ldap_authenticatable.rb new file mode 100644 index 000000000..065aa2de8 --- /dev/null +++ b/lib/devise/two_factor_ldap_authenticatable.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'net/ldap' +require 'devise/strategies/base' + +module Devise + module Strategies + class TwoFactorLdapAuthenticatable < Base + def valid? + valid_params? && mapping.to.respond_to?(:authenticate_with_ldap) + end + + def authenticate! + resource = mapping.to.authenticate_with_ldap(params[scope]) + + if resource && !resource.otp_required_for_login? + success!(resource) + else + fail(:invalid) + end + end + + protected + + def valid_params? + params[scope] && params[scope][:password].present? + end + end + end +end + +Warden::Strategies.add(:two_factor_ldap_authenticatable, Devise::Strategies::TwoFactorLdapAuthenticatable) diff --git a/lib/devise/two_factor_pam_authenticatable.rb b/lib/devise/two_factor_pam_authenticatable.rb new file mode 100644 index 000000000..5ce723b33 --- /dev/null +++ b/lib/devise/two_factor_pam_authenticatable.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'devise/strategies/base' + +module Devise + module Strategies + class TwoFactorPamAuthenticatable < Base + def valid? + valid_params? && mapping.to.respond_to?(:authenticate_with_pam) + end + + def authenticate! + resource = mapping.to.authenticate_with_pam(params[scope]) + + if resource && !resource.otp_required_for_login? + success!(resource) + else + fail(:invalid) + end + end + + protected + + def valid_params? + params[scope] && params[scope][:password].present? + end + end + end +end + +Warden::Strategies.add(:two_factor_pam_authenticatable, Devise::Strategies::TwoFactorPamAuthenticatable) -- cgit From b02169f124b8efefa33c10a14a5b45d5f9806e3d Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Wed, 25 Sep 2019 00:32:12 +0900 Subject: Cast multipart threshold to integer (#11944) --- config/initializers/paperclip.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config/initializers') diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index cfc95330c..f308c2841 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -25,7 +25,7 @@ if ENV['S3_ENABLED'] == 'true' s3_protocol: s3_protocol, s3_host_name: s3_hostname, s3_headers: { - 'X-Amz-Multipart-Threshold' => ENV.fetch('S3_MULTIPART_THRESHOLD') { 15.megabytes }, + 'X-Amz-Multipart-Threshold' => ENV.fetch('S3_MULTIPART_THRESHOLD') { 15.megabytes }.to_i, 'Cache-Control' => 'public, max-age=315576000, immutable', }, s3_permissions: ENV.fetch('S3_PERMISSION') { 'public-read' }, -- cgit From a5c558f0525a6ddcdddf6b7e61b554c3446fe2d5 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Wed, 25 Sep 2019 03:28:25 +0900 Subject: Hide error message on /heath (#11947) * Hide error message on /heath * update health_check --- Gemfile | 4 ++-- Gemfile.lock | 16 +++++++++++----- config/initializers/health_check.rb | 2 ++ 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'config/initializers') diff --git a/Gemfile b/Gemfile index 2ab313754..7ed1a4e6b 100644 --- a/Gemfile +++ b/Gemfile @@ -29,7 +29,7 @@ gem 'bootsnap', '~> 1.4', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.6' gem 'iso-639' -gem 'chewy', '~> 5.0' +gem 'chewy', '~> 5.1' gem 'cld3', '~> 3.2.4' gem 'devise', '~> 4.7' gem 'devise-two-factor', '~> 3.1' @@ -50,7 +50,7 @@ gem 'fastimage' gem 'goldfinger', '~> 2.1' gem 'hiredis', '~> 0.6' gem 'redis-namespace', '~> 1.5' -gem 'health_check', '~> 3.0' +gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b' gem 'htmlentities', '~> 4.3' gem 'http', '~> 3.3' gem 'http_accept_language', '~> 2.1' diff --git a/Gemfile.lock b/Gemfile.lock index a796d1aae..900f05ab3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,11 @@ +GIT + remote: https://github.com/ianheggie/health_check + revision: 0b799ead604f900ed50685e9b2d469cd2befba5b + ref: 0b799ead604f900ed50685e9b2d469cd2befba5b + specs: + health_check (4.0.0.pre) + rails (>= 4.0) + GIT remote: https://github.com/rtomayko/posix-spawn revision: 58465d2e213991f8afb13b984854a49fcdcc980c @@ -161,7 +169,7 @@ GEM case_transform (0.2) activesupport charlock_holmes (0.7.6) - chewy (5.0.1) + chewy (5.1.0) activesupport (>= 4.0) elasticsearch (>= 2.0.0) elasticsearch-dsl @@ -278,8 +286,6 @@ GEM concurrent-ruby (~> 1.0) hashdiff (1.0.0) hashie (3.6.0) - health_check (3.0.0) - railties (>= 5.0) heapy (0.1.4) highline (2.0.1) hiredis (0.6.3) @@ -687,7 +693,7 @@ DEPENDENCIES capistrano-yarn (~> 2.0) capybara (~> 3.29) charlock_holmes (~> 0.7.6) - chewy (~> 5.0) + chewy (~> 5.1) cld3 (~> 3.2.4) climate_control (~> 0.2) concurrent-ruby @@ -708,7 +714,7 @@ DEPENDENCIES fuubar (~> 2.4) goldfinger (~> 2.1) hamlit-rails (~> 0.2) - health_check (~> 3.0) + health_check! hiredis (~> 0.6) htmlentities (~> 4.3) http (~> 3.3) diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb index eece67b10..6f1e78fed 100644 --- a/config/initializers/health_check.rb +++ b/config/initializers/health_check.rb @@ -3,4 +3,6 @@ HealthCheck.setup do |config| config.standard_checks = %w(database migrations cache) config.full_checks = %w(database migrations cache) + + config.include_error_in_response_body = false end -- cgit From 5f69eb89e215fe7dc02cd0dc3f39b13f1945e88b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 29 Sep 2019 21:31:51 +0200 Subject: Add a nodeinfo endpoint (#12002) * Add nodeinfo endpoint * dont commit stuff from my local dev * consistant naming since we implimented 2.1 schema * Add some additional node info stuff * Add nodeinfo endpoint * dont commit stuff from my local dev * consistant naming since we implimented 2.1 schema * expanding this to include federation info * codeclimate feedback * CC feedback * using activeserializers seems like a good idea... * get rid of draft 2.1 version * Reimplement 2.1, also fix metaData -> metadata * Fix metaData -> metadata here too * Fix nodeinfo 2.1 tests * Implement cache for monthly user aggregate * Useless * Remove ostatus from the list of supported protocols * Fix nodeinfo's open_registration reading obsolete setting variable * Only serialize domain blocks with user-facing limitations * Do not needlessly list noop severity in nodeinfo * Only serialize domain blocks info in nodeinfo when they are set to be displayed to everyone * Enable caching for nodeinfo endpoints * Fix rendering nodeinfo * CodeClimate fixes * Please CodeClimate * Change InstancePresenter#active_user_count_months for clarity * Refactor NodeInfoSerializer#metadata * Remove nodeinfo 2.1 support as the schema doesn't exist * Clean-up --- app/controllers/well_known/nodeinfo_controller.rb | 19 ++++++++++ app/lib/activity_tracker.rb | 2 +- app/lib/nodeinfo/adapter.rb | 7 ++++ app/presenters/instance_presenter.rb | 4 +-- app/serializers/nodeinfo/discovery_serializer.rb | 11 ++++++ app/serializers/nodeinfo/serializer.rb | 41 ++++++++++++++++++++++ config/initializers/inflections.rb | 1 + config/routes.rb | 3 ++ .../well_known/nodeinfo_controller_spec.rb | 36 +++++++++++++++++++ 9 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 app/controllers/well_known/nodeinfo_controller.rb create mode 100644 app/lib/nodeinfo/adapter.rb create mode 100644 app/serializers/nodeinfo/discovery_serializer.rb create mode 100644 app/serializers/nodeinfo/serializer.rb create mode 100644 spec/controllers/well_known/nodeinfo_controller_spec.rb (limited to 'config/initializers') diff --git a/app/controllers/well_known/nodeinfo_controller.rb b/app/controllers/well_known/nodeinfo_controller.rb new file mode 100644 index 000000000..11a699ebc --- /dev/null +++ b/app/controllers/well_known/nodeinfo_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module WellKnown + class NodeInfoController < ActionController::Base + include CacheConcern + + before_action { response.headers['Vary'] = 'Accept' } + + def index + expires_in 3.days, public: true + render_with_cache json: {}, serializer: NodeInfo::DiscoverySerializer, adapter: NodeInfo::Adapter, expires_in: 3.days, root: 'nodeinfo' + end + + def show + expires_in 30.minutes, public: true + render_with_cache json: {}, serializer: NodeInfo::Serializer, adapter: NodeInfo::Adapter, expires_in: 30.minutes, root: 'nodeinfo' + end + end +end diff --git a/app/lib/activity_tracker.rb b/app/lib/activity_tracker.rb index ae3c11b6a..81303b715 100644 --- a/app/lib/activity_tracker.rb +++ b/app/lib/activity_tracker.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ActivityTracker - EXPIRE_AFTER = 90.days.seconds + EXPIRE_AFTER = 6.months.seconds class << self include Redisable diff --git a/app/lib/nodeinfo/adapter.rb b/app/lib/nodeinfo/adapter.rb new file mode 100644 index 000000000..1b48dcb98 --- /dev/null +++ b/app/lib/nodeinfo/adapter.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class NodeInfo::Adapter < ActiveModelSerializers::Adapter::Attributes + def self.default_key_transform + :camel_lower + end +end diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index becc92c2d..c4caeaa8c 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -20,8 +20,8 @@ class InstancePresenter Rails.cache.fetch('user_count') { User.confirmed.joins(:account).merge(Account.without_suspended).count } end - def active_user_count - Rails.cache.fetch('active_user_count') { Redis.current.pfcount(*(0..3).map { |i| "activity:logins:#{i.weeks.ago.utc.to_date.cweek}" }) } + def active_user_count(weeks = 4) + Rails.cache.fetch('active_user_count') { Redis.current.pfcount(*(0...weeks).map { |i| "activity:logins:#{i.weeks.ago.utc.to_date.cweek}" }) } end def status_count diff --git a/app/serializers/nodeinfo/discovery_serializer.rb b/app/serializers/nodeinfo/discovery_serializer.rb new file mode 100644 index 000000000..07ab2a6ee --- /dev/null +++ b/app/serializers/nodeinfo/discovery_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class NodeInfo::DiscoverySerializer < ActiveModel::Serializer + include RoutingHelper + + attribute :links + + def links + [{ rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0', href: nodeinfo_schema_url }] + end +end diff --git a/app/serializers/nodeinfo/serializer.rb b/app/serializers/nodeinfo/serializer.rb new file mode 100644 index 000000000..1a7d7a911 --- /dev/null +++ b/app/serializers/nodeinfo/serializer.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +class NodeInfo::Serializer < ActiveModel::Serializer + include RoutingHelper + + attributes :version, :software, :protocols, :usage + + def version + '2.0' + end + + def software + { name: 'mastodon', version: Mastodon::Version.to_s } + end + + def services + { outbound: [], inbound: [] } + end + + def protocols + %w(activitypub) + end + + def usage + { + users: { + total: instance_presenter.user_count, + active_month: instance_presenter.active_user_count(4), + active_halfyear: instance_presenter.active_user_count(24), + }, + + local_posts: instance_presenter.status_count, + } + end + + private + + def instance_presenter + @instance_presenter ||= InstancePresenter.new + end +end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index bf0cb52a3..c65153b0a 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -18,4 +18,5 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'PubSubHubbub' inflect.acronym 'ActivityStreams' inflect.acronym 'JsonLd' + inflect.acronym 'NodeInfo' end diff --git a/config/routes.rb b/config/routes.rb index f1a69cf5c..e43e201a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,10 +24,13 @@ Rails.application.routes.draw do end get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' } + get '.well-known/nodeinfo', to: 'well_known/nodeinfo#index', as: :nodeinfo, defaults: { format: 'json' } get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger get '.well-known/change-password', to: redirect('/auth/edit') get '.well-known/keybase-proof-config', to: 'well_known/keybase_proof_config#show' + get '/nodeinfo/2.0', to: 'well_known/nodeinfo#show', as: :nodeinfo_schema + get 'manifest', to: 'manifests#show', defaults: { format: 'json' } get 'intent', to: 'intents#show' get 'custom.css', to: 'custom_css#show', as: :custom_css diff --git a/spec/controllers/well_known/nodeinfo_controller_spec.rb b/spec/controllers/well_known/nodeinfo_controller_spec.rb new file mode 100644 index 000000000..12e1fa415 --- /dev/null +++ b/spec/controllers/well_known/nodeinfo_controller_spec.rb @@ -0,0 +1,36 @@ +require 'rails_helper' + +describe WellKnown::NodeInfoController, type: :controller do + render_views + + describe 'GET #index' do + it 'returns json document pointing to node info' do + get :index + + expect(response).to have_http_status(200) + expect(response.content_type).to eq 'application/json' + + json = body_as_json + + expect(json[:links]).to be_an Array + expect(json[:links][0][:rel]).to eq 'http://nodeinfo.diaspora.software/ns/schema/2.0' + expect(json[:links][0][:href]).to include 'nodeinfo/2.0' + end + end + + describe 'GET #show' do + it 'returns json document with node info properties' do + get :show + + expect(response).to have_http_status(200) + expect(response.content_type).to eq 'application/json' + + json = body_as_json + + expect(json[:version]).to eq '2.0' + expect(json[:usage]).to be_a Hash + expect(json[:software]).to be_a Hash + expect(json[:protocols]).to be_an Array + end + end +end -- cgit