1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# frozen_string_literal: true
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
force_ssl if: :https_enabled?
include Localized
include UserTrackingConcern
include SessionTrackingConcern
helper_method :current_account
helper_method :current_session
helper_method :current_theme
helper_method :single_user_mode?
helper_method :use_seamless_external_login?
rescue_from ActionController::RoutingError, with: :not_found
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
rescue_from ActionController::UnknownFormat, with: :not_acceptable
rescue_from Mastodon::NotPermittedError, with: :forbidden
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
before_action :check_user_permissions, if: :user_signed_in?
def raise_not_found
raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}"
end
private
def https_enabled?
Rails.env.production?
end
def store_current_location
store_location_for(:user, request.url) unless request.format == :json
end
def require_admin!
forbidden unless current_user&.admin?
end
def require_staff!
forbidden unless current_user&.staff?
end
def check_user_permissions
forbidden if current_user.disabled? || current_user.account.suspended?
end
def after_sign_out_path_for(_resource_or_scope)
new_user_session_path
end
protected
def truthy_param?(key)
ActiveModel::Type::Boolean.new.cast(params[key])
end
def forbidden
respond_with_error(403)
end
def not_found
respond_with_error(404)
end
def gone
respond_with_error(410)
end
def unprocessable_entity
respond_with_error(422)
end
def not_acceptable
respond_with_error(406)
end
def single_user_mode?
@single_user_mode ||= Rails.configuration.x.single_user_mode && Account.exists?
end
def use_seamless_external_login?
Devise.pam_authentication || Devise.ldap_authentication
end
def current_account
@current_account ||= current_user.try(:account)
end
def current_session
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
end
def current_theme
return Setting.theme unless Themes.instance.names.include? current_user&.setting_theme
current_user.setting_theme
end
def cache_collection(raw, klass)
return raw unless klass.respond_to?(:with_includes)
raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation)
cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id)
uncached_ids = raw.map(&:id) - cached_keys_with_value.keys
klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!)
unless uncached_ids.empty?
uncached = klass.where(id: uncached_ids).with_includes.each_with_object({}) { |item, h| h[item.id] = item }
uncached.each_value do |item|
Rails.cache.write(item, item)
end
end
raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact
end
def respond_with_error(code)
respond_to do |format|
format.any { head code }
format.html do
set_locale
render "errors/#{code}", layout: 'error', status: code
end
end
end
def render_cached_json(cache_key, **options)
options[:expires_in] ||= 3.minutes
cache_public = options.key?(:public) ? options.delete(:public) : true
content_type = options.delete(:content_type) || 'application/json'
data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do
yield.to_json
end
expires_in options[:expires_in], public: cache_public
render json: data, content_type: content_type
end
def set_cache_headers
response.headers['Vary'] = 'Accept'
end
def mark_cacheable!
skip_session!
expires_in 0, public: true
end
def skip_session!
request.session_options[:skip] = true
end
end
|