Class: UploadsController
- Inherits:
-
ApplicationController
- Object
- ActionController::Base
- ApplicationController
- UploadsController
- Includes:
- ExternalUploadHelpers, SecureUploadEndpointHelpers
- Defined in:
- app/controllers/uploads_controller.rb
Constant Summary collapse
- SECURE_REDIRECT_GRACE_SECONDS =
5
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
-
#_show_secure_deprecated ⇒ Object
Kept to avoid rebaking old posts with /show-secure-uploads/ in their contents, this will ensure the uploads in these posts continue to work in future.
- #create ⇒ Object
- #handle_secure_upload_request(upload, path_with_ext = nil) ⇒ Object
- #lookup_urls ⇒ Object
- #metadata ⇒ Object
- #show ⇒ Object
- #show_secure ⇒ Object
- #show_short ⇒ Object
Methods included from SecureUploadEndpointHelpers
#check_secure_upload_permission, #upload_from_full_url, #upload_from_path_and_extension
Methods included from ExternalUploadHelpers
#abort_multipart, #batch_presign_multipart_parts, #check_multipart_upload_exists, #complete_external_upload, #complete_multipart, #create_multipart, #generate_presigned_put
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
#_show_secure_deprecated ⇒ Object
Kept to avoid rebaking old posts with /show-secure-uploads/ in their contents, this will ensure the uploads in these posts continue to work in future.
155 156 157 |
# File 'app/controllers/uploads_controller.rb', line 155 def _show_secure_deprecated show_secure end |
#create ⇒ Object
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 |
# File 'app/controllers/uploads_controller.rb', line 25 def create # capture current user for block later on me = current_user RateLimiter.new( current_user, "uploads-per-minute", SiteSetting.max_uploads_per_minute, 1.minute.to_i, ).performed! type = if params[:upload_type].presence params[:upload_type] elsif params[:type].presence Discourse.deprecate( "the :type param of `POST /uploads` is deprecated, use the :upload_type param instead", since: "3.4", drop_from: "3.5", ) params[:type] else params.require(:upload_type) end # 50 characters ought to be enough for the upload type type = type.parameterize(separator: "_")[0..50] if type == "avatar" && ( SiteSetting.discourse_connect_overrides_avatar || !me.in_any_groups?(SiteSetting.uploaded_avatars_allowed_groups_map) ) return render json: failed_json, status: 422 end url = params[:url] file = params[:file] || params[:files]&.first pasted = params[:pasted] == "true" = params[:for_private_message] == "true" for_site_setting = params[:for_site_setting] == "true" is_api = is_api? retain_hours = params[:retain_hours].to_i # note, atm hijack is processed in its own context and has not access to controller # longer term we may change this hijack do begin info = UploadsController.create_upload( current_user: me, file: file, url: url, type: type, for_private_message: , for_site_setting: for_site_setting, pasted: pasted, is_api: is_api, retain_hours: retain_hours, ) rescue => e render json: failed_json.merge(message: e.&.split("\n")&.first), status: 422 else render json: UploadsController.serialize_upload(info), status: Upload === info ? 200 : 422 end end end |
#handle_secure_upload_request(upload, path_with_ext = nil) ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'app/controllers/uploads_controller.rb', line 184 def handle_secure_upload_request(upload, path_with_ext = nil) (upload) # defaults to public: false, so only cached by the client browser cache_seconds = SiteSetting.s3_presigned_get_url_expires_after_seconds - SECURE_REDIRECT_GRACE_SECONDS expires_in cache_seconds.seconds # url_for figures out the full URL, handling multisite DBs, # and will return a presigned URL for the upload if path_with_ext.blank? return( redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true ) end redirect_to Discourse.store.signed_url_for_path( path_with_ext, expires_in: SiteSetting.s3_presigned_get_url_expires_after_seconds, force_download: force_download?, ), allow_other_host: true end |
#lookup_urls ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'app/controllers/uploads_controller.rb', line 91 def lookup_urls params.permit(short_urls: []) uploads = [] if (params[:short_urls] && params[:short_urls].length > 0) PrettyText::Helpers .lookup_upload_urls(params[:short_urls]) .each do |short_url, paths| uploads << { short_url: short_url, url: paths[:url], short_path: paths[:short_path] } end end render json: uploads.to_json end |
#metadata ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'app/controllers/uploads_controller.rb', line 209 def params.require(:url) upload = Upload.get_from_url(params[:url]) raise Discourse::NotFound unless upload render json: { original_filename: upload.original_filename, width: upload.width, height: upload.height, human_filesize: upload.human_filesize, } end |
#show ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'app/controllers/uploads_controller.rb', line 106 def show # do not serve uploads requested via XHR to prevent XSS return xhr_not_allowed if request.xhr? return render_404 if !RailsMultisite::ConnectionManagement.has_db?(params[:site]) RailsMultisite::ConnectionManagement.with_connection(params[:site]) do |db| return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil? if upload = Upload.find_by(sha1: params[:sha]) || Upload.find_by(id: params[:id], url: request.env["PATH_INFO"]) unless Discourse.store.internal? local_store = FileStore::LocalStore.new return render_404 unless local_store.has_been_uploaded?(upload.url) end send_file_local_upload(upload) else render_404 end end end |
#show_secure ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'app/controllers/uploads_controller.rb', line 159 def show_secure # do not serve uploads requested via XHR to prevent XSS return xhr_not_allowed if request.xhr? path_with_ext = params[:extension].nil? ? params[:path] : "#{params[:path]}.#{params[:extension]}" upload = upload_from_path_and_extension(path_with_ext) return render_404 if upload.blank? return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil? return handle_secure_upload_request(upload, path_with_ext) if SiteSetting.secure_uploads? # we don't want to 404 here if secure uploads gets disabled # because all posts with secure uploads will show broken media # until rebaked, which could take some time # # if the upload is still secure, that means the ACL is probably still # private, so we don't want to go to the CDN url just yet otherwise we # will get a 403. if the upload is not secure we assume the ACL is public signed_secure_url = Discourse.store.signed_url_for_path(path_with_ext) redirect_to upload.secure? ? signed_secure_url : Discourse.store.cdn_url(upload.url), allow_other_host: true end |
#show_short ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'app/controllers/uploads_controller.rb', line 130 def show_short # do not serve uploads requested via XHR to prevent XSS return xhr_not_allowed if request.xhr? return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil? sha1 = Upload.sha1_from_base62_encoded(params[:base62]) if upload = Upload.find_by(sha1: sha1) return handle_secure_upload_request(upload) if upload.secure? && SiteSetting.secure_uploads? if Discourse.store.internal? send_file_local_upload(upload) else redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true end else render_404 end end |