Class: StaticController
- Inherits:
-
ApplicationController
- Object
- ActionController::Base
- ApplicationController
- StaticController
- Defined in:
- app/controllers/static_controller.rb
Constant Summary collapse
- PAGES_WITH_EMAIL_PARAM =
%w[login password_reset signup]
- MODAL_PAGES =
%w[password_reset signup]
- DEFAULT_PAGES =
{ "faq" => { redirect: "faq_url", topic_id: "guidelines_topic_id", }, "tos" => { redirect: "tos_url", topic_id: "tos_topic_id", }, "privacy" => { redirect: "privacy_policy_url", topic_id: "privacy_topic_id", }, }
- CUSTOM_PAGES =
Add via ‘#add_topic_static_page` in plugin API
{}
- FAVICON =
-"favicon"
Constants inherited from ApplicationController
ApplicationController::CHALLENGE_KEY, ApplicationController::HONEYPOT_KEY, ApplicationController::LEGACY_NO_THEMES, ApplicationController::LEGACY_NO_UNOFFICIAL_PLUGINS, ApplicationController::NO_PLUGINS, ApplicationController::NO_THEMES, ApplicationController::NO_UNOFFICIAL_PLUGINS, ApplicationController::SAFE_MODE
Constants included from CanonicalURL::ControllerExtensions
CanonicalURL::ControllerExtensions::ALLOWED_CANONICAL_PARAMS
Instance Attribute Summary
Attributes inherited from ApplicationController
Instance Method Summary collapse
- #cdn_asset ⇒ Object
-
#enter ⇒ Object
This method just redirects to a given url.
-
#favicon ⇒ Object
We need to be able to draw our favicon on a canvas, this happens when you enable the feature that draws the notification count on top of favicon (per user default off).
- #service_worker_asset ⇒ Object
- #show ⇒ Object
Methods inherited from ApplicationController
#application_layout, #can_cache_content?, #clear_notifications, #conditionally_allow_site_embedding, #current_homepage, #discourse_expires_in, #dont_cache_page, #ember_cli_required?, #fetch_user_from_params, #guardian, #handle_permalink, #handle_theme, #handle_unverified_request, #has_escaped_fragment?, #immutable_for, #login_method, #no_cookies, #perform_refresh_session, #post_ids_including_replies, #preload_json, #rate_limit_second_factor!, #redirect_with_client_support, #render_json_dump, #render_serialized, requires_plugin, #rescue_discourse_actions, #resolve_safe_mode, #secure_session, #serialize_data, #set_current_user_for_logs, #set_layout, #set_mobile_view, #set_mp_snapshot_fields, #show_browser_update?, #store_preloaded, #use_crawler_layout?, #with_resolved_locale
Methods included from VaryHeader
Methods included from ThemeResolver
Methods included from ReadOnlyMixin
#add_readonly_header, #allowed_in_staff_writes_only_mode?, #block_if_readonly_mode, #check_readonly_mode, #get_or_check_readonly_mode, #get_or_check_staff_writes_only_mode, included, #staff_writes_only_mode?
Methods included from Hijack
Methods included from GlobalPath
#cdn_path, #cdn_relative_path, #full_cdn_url, #path, #upload_cdn_path
Methods included from JsonError
Methods included from CanonicalURL::ControllerExtensions
#canonical_url, #default_canonical, included
Methods included from CurrentUser
#clear_current_user, #current_user, has_auth_cookie?, #is_api?, #is_user_api?, #log_off_user, #log_on_user, lookup_from_env, #refresh_session
Instance Method Details
#cdn_asset ⇒ Object
208 209 210 211 212 |
# File 'app/controllers/static_controller.rb', line 208 def cdn_asset is_asset_path serve_asset end |
#enter ⇒ Object
This method just redirects to a given url. It’s used when an ajax login was successful but we want the browser to see a post of a login form so that it offers to remember your password.
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 |
# File 'app/controllers/static_controller.rb', line 122 def enter params.delete(:username) params.delete(:password) destination = path("/") redirect_location = params[:redirect] if redirect_location.present? && !redirect_location.is_a?(String) raise Discourse::InvalidParameters.new(:redirect) elsif redirect_location.present? && begin forum_uri = URI(Discourse.base_url) uri = URI(redirect_location) if uri.path.present? && !uri.path.starts_with?(login_path) && (uri.host.blank? || uri.host == forum_uri.host) && uri.path =~ %r{\A\/{1}[^\.\s]*\z} destination = "#{uri.path}#{uri.query ? "?#{uri.query}" : ""}" end rescue URI::Error # Do nothing if the URI is invalid end end redirect_to(destination, allow_other_host: false) end |
#favicon ⇒ Object
We need to be able to draw our favicon on a canvas, this happens when you enable the feature that draws the notification count on top of favicon (per user default off)
With s3 the original upload is going to be stored at s3, we don’t have a local copy of the favicon. To allow canvas to work with s3 we are going to need to add special CORS headers and use a special crossorigin hint on the original, this is not easily workable.
Forcing all consumers to set magic CORS headers on a CDN is also not workable for us.
So we cache the favicon in redis and serve it out real quick with a huge expiry, we also cache these assets in nginx so it is bypassed if needed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'app/controllers/static_controller.rb', line 162 def favicon is_asset_path hijack do data = DistributedMemoizer.memoize("FAVICON#{SiteIconManager.favicon_url}", 60 * 30) do favicon = SiteIconManager.favicon next "" unless favicon if Discourse.store.external? begin file = FileHelper.download( Discourse.store.cdn_url(favicon.url), max_file_size: favicon.filesize, tmp_file_name: FAVICON, follow_redirect: true, ) file&.read || "" rescue => e ProblemCheckTracker[:bad_favicon_url].problem! Rails.logger.debug("Failed to fetch favicon #{favicon.url}: #{e}\n#{e.backtrace}") "" ensure file&.unlink end else File.read(Rails.root.join("public", favicon.url[1..-1])) end end if data.bytesize == 0 @@default_favicon ||= File.read(Rails.root + "public/images/default-favicon.png") response.headers["Content-Length"] = @@default_favicon.bytesize.to_s render body: @@default_favicon, content_type: "image/png" else immutable_for 1.year response.headers["Expires"] = 1.year.from_now.httpdate response.headers["Content-Length"] = data.bytesize.to_s response.headers["Last-Modified"] = Time.new(2000, 01, 01).httpdate render body: data, content_type: "image/png" end end end |
#service_worker_asset ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'app/controllers/static_controller.rb', line 214 def service_worker_asset is_asset_path respond_to do |format| format.js do # https://github.com/w3c/ServiceWorker/blob/master/explainer.md#updating-a-service-worker # Maximum cache that the service worker will respect is 24 hours. # However, ensure that these may be cached and served for longer on servers. immutable_for 1.year if Rails.application.assets_manifest.assets["service-worker.js"] path = File.( Rails.root + "public/assets/#{Rails.application.assets_manifest.assets["service-worker.js"]}", ) response.headers["Last-Modified"] = File.ctime(path).httpdate end content = Rails.application.assets_manifest.find_sources("service-worker.js").first base_url = File.dirname(helpers.script_asset_path("service-worker")) content = content.sub(%r{^//# sourceMappingURL=(service-worker-.+\.map)$}) do "//# sourceMappingURL=#{base_url}/#{Regexp.last_match(1)}" end render(plain: content, content_type: "application/javascript") end end end |
#show ⇒ Object
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 |
# File 'app/controllers/static_controller.rb', line 30 def show if current_user && (params[:id] == "login" || params[:id] == "signup") return redirect_to(path "/") end if SiteSetting.login_required? && current_user.nil? && %w[faq guidelines].include?(params[:id]) return redirect_to path("/login") end rename_faq = SiteSetting.experimental_rename_faq_to_guidelines if rename_faq redirect_paths = %w[/rules /conduct] redirect_paths << "/faq" if SiteSetting.faq_url.blank? return redirect_to(path("/guidelines")) if redirect_paths.include?(request.path) end map = DEFAULT_PAGES.deep_merge(CUSTOM_PAGES) @page = params[:id] if map.has_key?(@page) site_setting_key = map[@page][:redirect] url = SiteSetting.get(site_setting_key) if site_setting_key return redirect_to(url, allow_other_host: true) if url.present? end # The /guidelines route ALWAYS shows our FAQ, ignoring the faq_url site setting. @page = "faq" if @page == "guidelines" # Don't allow paths like ".." or "/" or anything hacky like that @page = @page.gsub(/[^a-z0-9\_\-]/, "") if map.has_key?(@page) topic_id = map[@page][:topic_id] topic_id = instance_exec(&topic_id) if topic_id.is_a?(Proc) @topic = Topic.find_by_id(SiteSetting.get(topic_id)) raise Discourse::NotFound unless @topic page_name = if @page == "faq" rename_faq ? "guidelines" : "faq" else @page end title_prefix = if I18n.exists?("js.#{page_name}") I18n.t("js.#{page_name}") else @topic.title end @title = "#{title_prefix} - #{SiteSetting.title}" @body = @topic.posts.first.cooked @faq_overridden = !SiteSetting.faq_url.blank? @experimental_rename_faq_to_guidelines = rename_faq render :show, layout: !request.xhr?, formats: [:html] return end @title = SiteSetting.title.dup if SiteSetting.short_site_description.present? @title << " - #{SiteSetting.short_site_description}" end if I18n.exists?("static.#{@page}") render html: I18n.t("static.#{@page}"), layout: !request.xhr?, formats: [:html] return end if PAGES_WITH_EMAIL_PARAM.include?(@page) && params[:email] [:email] = { value: params[:email], expires: 1.day.from_now } end if lookup_context.find_all("static/#{@page}").any? render "static/#{@page}", layout: !request.xhr?, formats: [:html] return end if MODAL_PAGES.include?(@page) render html: nil, layout: true return end raise Discourse::NotFound end |