discourse/config/routes.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

991 lines
50 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2013-12-23 18:50:36 -05:00
require "sidekiq/web"
require "mini_scheduler/web"
2013-02-05 14:16:51 -05:00
# The following constants have been replaced with `RouteFormat` and are deprecated.
USERNAME_ROUTE_FORMAT = /[%\w.\-]+?/ unless defined? USERNAME_ROUTE_FORMAT
BACKUP_ROUTE_FORMAT = /.+\.(sql\.gz|tar\.gz|tgz)/i unless defined? BACKUP_ROUTE_FORMAT
2013-02-05 14:16:51 -05:00
Discourse::Application.routes.draw do
scope path: nil, constraints: { format: /(json|html|\*\/\*)/ } do
relative_url_root = (defined?(Rails.configuration.relative_url_root) && Rails.configuration.relative_url_root) ? Rails.configuration.relative_url_root + '/' : '/'
2013-02-05 14:16:51 -05:00
match "/404", to: "exceptions#not_found", via: [:get, :post]
2014-04-29 15:17:40 -04:00
get "/404-body" => "exceptions#not_found_body"
2020-06-04 22:49:31 -04:00
get "/bootstrap" => "bootstrap#index"
2020-06-04 22:49:31 -04:00
post "webhooks/aws" => "webhooks#aws"
2016-06-06 13:47:45 -04:00
post "webhooks/mailgun" => "webhooks#mailgun"
post "webhooks/mailjet" => "webhooks#mailjet"
2016-06-13 06:31:01 -04:00
post "webhooks/mandrill" => "webhooks#mandrill"
2020-02-11 10:09:07 -05:00
post "webhooks/postmark" => "webhooks#postmark"
post "webhooks/sendgrid" => "webhooks#sendgrid"
2016-09-27 01:13:34 -04:00
post "webhooks/sparkpost" => "webhooks#sparkpost"
2020-06-04 22:49:31 -04:00
scope path: nil, constraints: { format: /.*/ } do
if Rails.env.development?
mount Sidekiq::Web => "/sidekiq"
mount Logster::Web => "/logs"
else
# only allow sidekiq in master site
mount Sidekiq::Web => "/sidekiq", constraints: AdminConstraint.new(require_master: true)
mount Logster::Web => "/logs", constraints: AdminConstraint.new
2020-06-04 22:49:31 -04:00
end
end
resources :about do
collection do
get "live_post_counts"
2020-06-04 22:49:31 -04:00
end
end
2014-08-11 16:59:00 -04:00
get "finish-installation" => "finish_installation#index"
get "finish-installation/register" => "finish_installation#register"
post "finish-installation/register" => "finish_installation#register"
get "finish-installation/confirm-email" => "finish_installation#confirm_email"
put "finish-installation/resend-email" => "finish_installation#resend_email"
2020-06-04 22:49:31 -04:00
get "pub/check-slug" => "published_pages#check_slug"
get "pub/by-topic/:topic_id" => "published_pages#details"
put "pub/by-topic/:topic_id" => "published_pages#upsert"
delete "pub/by-topic/:topic_id" => "published_pages#destroy"
get "pub/:slug" => "published_pages#show"
2020-06-04 22:49:31 -04:00
resources :directory_items
2020-06-04 22:49:31 -04:00
get "site" => "site#site"
namespace :site do
get "settings"
get "custom_html"
get "banner"
get "emoji"
end
get "site/basic-info" => 'site#basic_info'
2017-03-10 08:16:00 -05:00
get "site/statistics" => 'site#statistics'
2013-12-23 18:50:36 -05:00
get "srv/status" => "forums#status"
2013-02-05 14:16:51 -05:00
2016-08-25 13:14:56 -04:00
get "wizard" => "wizard#index"
get 'wizard/steps' => 'steps#index'
2016-09-07 18:04:01 -04:00
get 'wizard/steps/:id' => "wizard#index"
2016-08-25 13:14:56 -04:00
put 'wizard/steps/:id' => "steps#update"
namespace :admin, constraints: StaffConstraint.new do
2013-12-23 18:50:36 -05:00
get "" => "admin#index"
2013-02-05 14:16:51 -05:00
get 'plugins' => 'plugins#index'
2013-11-13 14:02:47 -05:00
resources :site_settings, constraints: AdminConstraint.new do
collection do
2013-12-23 18:50:36 -05:00
get "category/:id" => "site_settings#index"
2013-11-13 14:02:47 -05:00
end
put "user_count" => "site_settings#user_count"
2013-11-13 14:02:47 -05:00
end
get "reports" => "reports#index"
get "reports/bulk" => "reports#bulk"
2013-12-23 18:50:36 -05:00
get "reports/:type" => "reports#show"
resources :groups, only: [:create] do
member do
put "owners" => "groups#add_owners"
delete "owners" => "groups#remove_owner"
put "primary" => "groups#set_primary"
end
end
resources :groups, except: [:create], constraints: AdminConstraint.new do
2013-05-08 01:20:38 -04:00
collection do
put "automatic_membership_count" => "groups#automatic_membership_count"
2013-05-08 01:20:38 -04:00
end
end
2013-05-08 01:20:38 -04:00
get "groups/:type" => "groups#show", constraints: AdminConstraint.new
get "groups/:type/:id" => "groups#show", constraints: AdminConstraint.new
resources :users, id: RouteFormat.username, except: [:show] do
2013-02-05 14:16:51 -05:00
collection do
2017-04-26 23:02:59 -04:00
get "list" => "users#index"
2013-12-23 18:50:36 -05:00
get "list/:query" => "users#index"
get "ip-info" => "users#ip_info"
delete "delete-others-with-same-ip" => "users#delete_other_accounts_with_same_ip"
get "total-others-with-same-ip" => "users#total_other_accounts_with_same_ip"
2013-12-23 18:50:36 -05:00
put "approve-bulk" => "users#approve_bulk"
2020-06-04 22:49:31 -04:00
end
delete "penalty_history", constraints: AdminConstraint.new
2013-12-23 18:50:36 -05:00
put "suspend"
put "delete_posts_batch"
2013-12-23 18:50:36 -05:00
put "unsuspend"
put "revoke_admin", constraints: AdminConstraint.new
put "grant_admin", constraints: AdminConstraint.new
put "revoke_moderation", constraints: AdminConstraint.new
put "grant_moderation", constraints: AdminConstraint.new
put "approve"
2014-06-05 23:02:52 -04:00
post "log_out", constraints: AdminConstraint.new
2013-12-23 18:50:36 -05:00
put "activate"
put "deactivate"
2017-11-10 12:18:08 -05:00
put "silence"
put "unsilence"
2013-12-23 18:50:36 -05:00
put "trust_level"
put "trust_level_lock"
put "primary_group"
post "groups" => "users#add_group", constraints: AdminConstraint.new
delete "groups/:group_id" => "users#remove_group", constraints: AdminConstraint.new
get "badges"
2014-09-24 20:19:26 -04:00
get "leader_requirements" => "users#tl3_requirements"
get "tl3_requirements"
put "anonymize"
post "merge"
post "reset_bounce_score"
put "disable_second_factor"
delete "sso_record"
2013-02-05 14:16:51 -05:00
end
get "users/:id.json" => 'users#show', defaults: { format: 'json' }
get 'users/:id/:username' => 'users#show', constraints: { username: RouteFormat.username }
get 'users/:id/:username/badges' => 'users#show'
get 'users/:id/:username/tl3_requirements' => 'users#show'
2013-02-05 14:16:51 -05:00
post "users/sync_sso" => "users#sync_sso", constraints: AdminConstraint.new
resources :impersonate, constraints: AdminConstraint.new
resources :email, constraints: AdminConstraint.new do
collection do
post "test"
2014-02-14 18:50:08 -05:00
get "sent"
get "skipped"
2016-05-02 17:15:32 -04:00
get "bounced"
get "received"
get "rejected"
get "/incoming/:id/raw" => "email#raw_email"
get "/incoming/:id" => "email#incoming"
get "/incoming_from_bounced/:id" => "email#incoming_from_bounced"
2013-12-23 18:50:36 -05:00
get "preview-digest" => "email#preview_digest"
get "send-digest" => "email#send_digest"
get "smtp_should_reject"
post "handle_mail"
get "advanced-test"
post "advanced-test" => "email#advanced_test"
end
end
2020-06-04 22:49:31 -04:00
2013-12-23 18:50:36 -05:00
scope "/logs" do
resources :staff_action_logs, only: [:index]
get 'staff_action_logs/:id/diff' => 'staff_action_logs#diff'
resources :screened_emails, only: [:index, :destroy]
resources :screened_ip_addresses, only: [:index, :create, :update, :destroy] do
collection do
post "roll_up"
2020-06-04 22:49:31 -04:00
end
end
resources :screened_urls, only: [:index]
2017-11-14 19:13:50 -05:00
resources :search_logs, only: [:index]
get 'search_logs/term/' => 'search_logs#term'
end
2013-08-01 21:30:13 -04:00
get "/logs" => "staff_action_logs#index"
2020-06-04 22:49:31 -04:00
# alias
get '/logs/watched_words', to: redirect(relative_url_root + 'admin/customize/watched_words')
get '/logs/watched_words/*path', to: redirect(relative_url_root + 'admin/customize/watched_words/%{path}')
get "customize" => "color_schemes#index", constraints: AdminConstraint.new
get "customize/themes" => "themes#index", constraints: AdminConstraint.new
get "customize/colors" => "color_schemes#index", constraints: AdminConstraint.new
get "customize/colors/:id" => "color_schemes#index", constraints: AdminConstraint.new
2015-07-15 08:54:28 -04:00
get "customize/permalinks" => "permalinks#index", constraints: AdminConstraint.new
get "customize/embedding" => "embedding#show", constraints: AdminConstraint.new
put "customize/embedding" => "embedding#update", constraints: AdminConstraint.new
2020-06-04 22:49:31 -04:00
resources :themes, constraints: AdminConstraint.new
2020-06-04 22:49:31 -04:00
post "themes/import" => "themes#import"
post "themes/upload_asset" => "themes#upload_asset"
post "themes/generate_key_pair" => "themes#generate_key_pair"
get "themes/:id/preview" => "themes#preview"
put "themes/:id/setting" => "themes#update_single_setting"
2020-06-04 22:49:31 -04:00
scope "/customize", constraints: AdminConstraint.new do
resources :user_fields, constraints: AdminConstraint.new
2014-12-22 19:12:26 -05:00
resources :emojis, constraints: AdminConstraint.new
2020-06-04 22:49:31 -04:00
get 'themes/:id/:target/:field_name/edit' => 'themes#index'
get 'themes/:id' => 'themes#index'
get "themes/:id/export" => "themes#export"
2020-06-04 22:49:31 -04:00
# They have periods in their URLs often:
get 'site_texts' => 'site_texts#index'
get 'site_texts/:id.json' => 'site_texts#show', constraints: { id: /[\w.\-\+\%\&]+/i }
get 'site_texts/:id' => 'site_texts#show', constraints: { id: /[\w.\-\+\%\&]+/i }
put 'site_texts/:id.json' => 'site_texts#update', constraints: { id: /[\w.\-\+\%\&]+/i }
put 'site_texts/:id' => 'site_texts#update', constraints: { id: /[\w.\-\+\%\&]+/i }
delete 'site_texts/:id.json' => 'site_texts#revert', constraints: { id: /[\w.\-\+\%\&]+/i }
delete 'site_texts/:id' => 'site_texts#revert', constraints: { id: /[\w.\-\+\%\&]+/i }
2020-06-04 22:49:31 -04:00
get 'reseed' => 'site_texts#get_reseed_options'
post 'reseed' => 'site_texts#reseed'
2020-06-04 22:49:31 -04:00
2016-04-06 15:57:54 -04:00
get 'email_templates' => 'email_templates#index'
get 'email_templates/(:id)' => 'email_templates#show', constraints: { id: /[0-9a-z_.]+/ }
put 'email_templates/(:id)' => 'email_templates#update', constraints: { id: /[0-9a-z_.]+/ }
delete 'email_templates/(:id)' => 'email_templates#revert', constraints: { id: /[0-9a-z_.]+/ }
2020-06-04 22:49:31 -04:00
get 'robots' => 'robots_txt#show'
put 'robots.json' => 'robots_txt#update'
delete 'robots.json' => 'robots_txt#reset'
2020-06-04 22:49:31 -04:00
resource :email_style, only: [:show, :update]
get 'email_style/:field' => 'email_styles#show', constraints: { field: /html|css/ }
end
resources :embeddable_hosts, constraints: AdminConstraint.new
resources :color_schemes, constraints: AdminConstraint.new
resources :permalinks, constraints: AdminConstraint.new
scope "/customize" do
resources :watched_words, only: [:index, :create, :update, :destroy] do
collection do
get "action/:id" => "watched_words#index"
get "action/:id/download" => "watched_words#download"
delete "action/:id" => "watched_words#clear_all"
end
end
post "watched_words/upload" => "watched_words#upload"
end
2013-12-23 18:50:36 -05:00
get "version_check" => "versions#show"
2014-02-12 23:33:40 -05:00
2019-04-01 06:39:49 -04:00
get "dashboard" => "dashboard#index"
get "dashboard/general" => "dashboard#general"
get "dashboard/moderation" => "dashboard#moderation"
get "dashboard/security" => "dashboard#security"
get "dashboard/reports" => "dashboard#reports"
get "dashboard/new-features" => "dashboard#new_features"
put "dashboard/mark-new-features-as-seen" => "dashboard#mark_new_features_as_seen"
resources :dashboard, only: [:index] do
collection do
2013-12-23 18:50:36 -05:00
get "problems"
2020-06-04 22:49:31 -04:00
end
end
2014-02-12 23:33:40 -05:00
resources :api, only: [:index], constraints: AdminConstraint.new do
2013-03-25 21:04:28 -04:00
collection do
resources :keys, controller: 'api', only: [:index, :show, :update, :create, :destroy] do
collection do
get 'scopes' => 'api#scopes'
end
member do
post "revoke" => "api#revoke_key"
post "undo-revoke" => "api#undo_revoke_key"
2020-06-04 22:49:31 -04:00
end
end
resources :web_hooks
get 'web_hook_events/:id' => 'web_hooks#list_events', as: :web_hook_events
get 'web_hooks/:id/events' => 'web_hooks#list_events'
get 'web_hooks/:id/events/bulk' => 'web_hooks#bulk_events'
post 'web_hooks/:web_hook_id/events/:event_id/redeliver' => 'web_hooks#redeliver_event'
post 'web_hooks/:id/ping' => 'web_hooks#ping'
2020-06-04 22:49:31 -04:00
end
2013-03-25 21:04:28 -04:00
end
2014-02-12 23:33:40 -05:00
resources :backups, only: [:index, :create], constraints: AdminConstraint.new do
member do
get "" => "backups#show", constraints: { id: RouteFormat.backup }
put "" => "backups#email", constraints: { id: RouteFormat.backup }
delete "" => "backups#destroy", constraints: { id: RouteFormat.backup }
post "restore" => "backups#restore", constraints: { id: RouteFormat.backup }
2014-02-12 23:33:40 -05:00
end
collection do
get "logs" => "backups#logs"
get "status" => "backups#status"
delete "cancel" => "backups#cancel"
post "rollback" => "backups#rollback"
2014-02-12 23:33:40 -05:00
put "readonly" => "backups#readonly"
2014-05-27 16:14:37 -04:00
get "upload" => "backups#check_backup_chunk"
post "upload" => "backups#upload_backup_chunk"
get "upload_url" => "backups#create_upload_url"
2020-06-04 22:49:31 -04:00
end
2014-02-12 23:33:40 -05:00
end
2014-02-14 18:50:08 -05:00
2014-03-05 07:52:20 -05:00
resources :badges, constraints: AdminConstraint.new do
collection do
get "/award/:badge_id" => "badges#award"
post "/award/:badge_id" => "badges#mass_award"
2014-03-05 07:52:20 -05:00
get "types" => "badges#badge_types"
2014-07-27 04:22:01 -04:00
post "badge_groupings" => "badges#save_badge_groupings"
post "preview" => "badges#preview"
2020-06-04 22:49:31 -04:00
end
2014-03-05 07:52:20 -05:00
end
Upgrade to FontAwesome 5 (take two) (#6673) * Add missing icons to set * Revert FA5 revert This reverts commit 42572ff * use new SVG syntax in locales * Noscript page changes (remove login button, center "powered by" footer text) * Cast wider net for SVG icons in settings - include any _icon setting for SVG registry (offers better support for plugin settings) - let themes store multiple pipe-delimited icons in a setting - also replaces broken onebox image icon with SVG reference in cooked post processor * interpolate icons in locales * Fix composer whisper icon alignment * Add support for stacked icons * SECURITY: enforce hostname to match discourse hostname This ensures that the hostname rails uses for various helpers always matches the Discourse hostname * load SVG sprite with pre-initializers * FIX: enable caching on SVG sprites * PERF: use JSONP for SVG sprites so they are served from CDN This avoids needing to deal with CORS for loading of the SVG Note, added the svg- prefix to the filename so we can quickly tell in dev tools what the file is * Add missing SVG sprite JSONP script to CSP * Upgrade to FA 5.5.0 * Add support for all FA4.7 icons - adds complete frontend and backend for renamed FA4.7 icons - improves performance of SvgSprite.bundle and SvgSprite.all_icons * Fix group avatar flair preview - adds an endpoint at /svg-sprites/search/:keyword - adds frontend ajax call that pulls icon in avatar flair preview even when it is not in subset * Remove FA 4.7 font files
2018-11-26 16:49:57 -05:00
end # admin namespace
2013-02-05 14:16:51 -05:00
2013-12-23 18:50:36 -05:00
get "email/unsubscribe/:key" => "email#unsubscribe", as: "email_unsubscribe"
get "email/unsubscribed" => "email#unsubscribed", as: "email_unsubscribed"
post "email/unsubscribe/:key" => "email#perform_unsubscribe", as: "email_perform_unsubscribe"
2013-02-05 14:16:51 -05:00
2016-08-25 16:33:29 -04:00
get "extra-locales/:bundle" => "extra_locales#show"
resources :session, id: RouteFormat.username, only: [:create, :destroy, :become] do
2018-03-27 23:31:43 -04:00
if !Rails.env.production?
get 'become'
end
collection do
2013-12-23 18:50:36 -05:00
post "forgot_password"
2020-06-04 22:49:31 -04:00
end
2013-02-05 14:16:51 -05:00
end
get "review" => "reviewables#index" # For ember app
get "review/:reviewable_id" => "reviewables#show", constraints: { reviewable_id: /\d+/ }
get "review/:reviewable_id/explain" => "reviewables#explain", constraints: { reviewable_id: /\d+/ }
get "review/count" => "reviewables#count"
get "review/topics" => "reviewables#topics"
get "review/settings" => "reviewables#settings"
put "review/settings" => "reviewables#settings"
put "review/:reviewable_id/perform/:action_id" => "reviewables#perform", constraints: {
reviewable_id: /\d+/,
action_id: /[a-z\_]+/
}
put "review/:reviewable_id" => "reviewables#update", constraints: { reviewable_id: /\d+/ }
delete "review/:reviewable_id" => "reviewables#destroy", constraints: { reviewable_id: /\d+/ }
2020-06-04 22:49:31 -04:00
resources :reviewable_claimed_topics
2020-06-04 22:49:31 -04:00
get "session/sso" => "session#sso"
get "session/sso_login" => "session#sso_login"
get "session/sso_provider" => "session#sso_provider"
get "session/current" => "session#current"
2013-12-23 18:50:36 -05:00
get "session/csrf" => "session#csrf"
get "session/hp" => "session#get_honeypot_value"
get "session/email-login/:token" => "session#email_login_info"
post "session/email-login/:token" => "session#email_login"
get "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ }
post "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ }
get "composer_messages" => "composer_messages#index"
2020-06-04 22:49:31 -04:00
2013-02-05 14:16:51 -05:00
resources :static
post "login" => "static#enter"
get "login" => "static#show", id: "login"
get "password-reset" => "static#show", id: "password_reset"
get "faq" => "static#show", id: "faq"
get "tos" => "static#show", id: "tos", as: 'tos'
get "privacy" => "static#show", id: "privacy", as: 'privacy'
get "signup" => "static#show", id: "signup"
get "login-preferences" => "static#show", id: "login"
2020-06-04 22:49:31 -04:00
%w{guidelines rules conduct}.each do |faq_alias|
get faq_alias => "static#show", id: "guidelines", as: faq_alias
end
get "my/*path", to: 'users#my_redirect'
get ".well-known/change-password", to: redirect(relative_url_root + 'my/preferences/account', status: 302)
get "user-cards" => "users#cards", format: :json
get "directory-columns" => "directory_columns#index", format: :json
get "edit-directory-columns" => "edit_directory_columns#index", format: :json
put "edit-directory-columns" => "edit_directory_columns#update", format: :json
2017-03-30 22:04:00 -04:00
%w{users u}.each_with_index do |root_path, index|
get "#{root_path}" => "users#index", constraints: { format: 'html' }
resources :users, except: [:index, :new, :show, :update, :destroy], path: root_path do
2017-03-30 22:04:00 -04:00
collection do
get "check_username"
get "check_email"
2017-03-30 22:04:00 -04:00
get "is_local_username"
2020-06-04 22:49:31 -04:00
end
2017-03-30 22:04:00 -04:00
end
2020-06-04 22:49:31 -04:00
post "#{root_path}/second_factors" => "users#list_second_factors"
put "#{root_path}/second_factor" => "users#update_second_factor"
2020-06-04 22:49:31 -04:00
post "#{root_path}/create_second_factor_security_key" => "users#create_second_factor_security_key"
post "#{root_path}/register_second_factor_security_key" => "users#register_second_factor_security_key"
put "#{root_path}/security_key" => "users#update_security_key"
post "#{root_path}/create_second_factor_totp" => "users#create_second_factor_totp"
post "#{root_path}/enable_second_factor_totp" => "users#enable_second_factor_totp"
put "#{root_path}/disable_second_factor" => "users#disable_second_factor"
2020-06-04 22:49:31 -04:00
2018-06-28 04:12:32 -04:00
put "#{root_path}/second_factors_backup" => "users#create_second_factor_backup"
2020-06-04 22:49:31 -04:00
put "#{root_path}/update-activation-email" => "users#update_activation_email"
post "#{root_path}/email-login" => "users#email_login"
2017-03-30 22:04:00 -04:00
get "#{root_path}/admin-login" => "users#admin_login"
put "#{root_path}/admin-login" => "users#admin_login"
post "#{root_path}/toggle-anon" => "users#toggle_anon"
post "#{root_path}/read-faq" => "users#read_faq"
get "#{root_path}/search/users" => "users#search_users"
2020-06-04 22:49:31 -04:00
get({ "#{root_path}/account-created/" => "users#account_created" }.merge(index == 1 ? { as: :users_account_created } : { as: :old_account_created }))
2020-06-04 22:49:31 -04:00
get "#{root_path}/account-created/resent" => "users#account_created"
get "#{root_path}/account-created/edit-email" => "users#account_created"
2020-01-15 05:27:12 -05:00
get({ "#{root_path}/password-reset/:token" => "users#password_reset_show" }.merge(index == 1 ? { as: :password_reset_token } : {}))
2017-03-30 22:04:00 -04:00
get "#{root_path}/confirm-email-token/:token" => "users#confirm_email_token", constraints: { format: 'json' }
2020-01-15 05:27:12 -05:00
put "#{root_path}/password-reset/:token" => "users#password_reset_update"
2017-03-30 22:04:00 -04:00
get "#{root_path}/activate-account/:token" => "users#activate_account"
put({ "#{root_path}/activate-account/:token" => "users#perform_account_activation" }.merge(index == 1 ? { as: 'perform_activate_account' } : {}))
2020-06-04 22:49:31 -04:00
get "#{root_path}/confirm-old-email/:token" => "users_email#show_confirm_old_email"
put "#{root_path}/confirm-old-email" => "users_email#confirm_old_email"
2020-06-04 22:49:31 -04:00
get "#{root_path}/confirm-new-email/:token" => "users_email#show_confirm_new_email"
put "#{root_path}/confirm-new-email" => "users_email#confirm_new_email"
2020-06-04 22:49:31 -04:00
get({
"#{root_path}/confirm-admin/:token" => "users#confirm_admin",
constraints: { token: /[0-9a-f]+/ }
}.merge(index == 1 ? { as: 'confirm_admin' } : {}))
post "#{root_path}/confirm-admin/:token" => "users#confirm_admin", constraints: { token: /[0-9a-f]+/ }
get "#{root_path}/:username/private-messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/private-messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/messages/group/:group_name" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username }
get "#{root_path}/:username/messages/group/:group_name/archive" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username }
get "#{root_path}/:username/messages/tags/:tag_id" => "user_actions#private_messages", constraints: StaffConstraint.new
get "#{root_path}/:username.json" => "users#show", constraints: { username: RouteFormat.username }, defaults: { format: :json }
get({ "#{root_path}/:username" => "users#show", constraints: { username: RouteFormat.username } }.merge(index == 1 ? { as: 'user' } : {}))
put "#{root_path}/:username" => "users#update", constraints: { username: RouteFormat.username }, defaults: { format: :json }
get "#{root_path}/:username/emails" => "users#check_emails", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/sso-email" => "users#check_sso_email", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/sso-payload" => "users#check_sso_payload", constraints: { username: RouteFormat.username }
2020-06-05 12:42:12 -04:00
get "#{root_path}/:username/preferences" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/email" => "users_email#index", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/account" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/security" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/profile" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/emails" => "users#preferences", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/preferences/primary-email" => "users#update_primary_email", format: :json, constraints: { username: RouteFormat.username }
delete "#{root_path}/:username/preferences/email" => "users#destroy_email", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/notifications" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/categories" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/users" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/tags" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/interface" => "users#preferences", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/apps" => "users#preferences", constraints: { username: RouteFormat.username }
post "#{root_path}/:username/preferences/email" => "users_email#create", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/preferences/email" => "users_email#update", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/badge_title" => "users#preferences", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/preferences/badge_title" => "users#badge_title", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/username" => "users#preferences", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/preferences/username" => "users#username", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/preferences/second-factor" => "users#preferences", constraints: { username: RouteFormat.username }
2018-06-28 04:12:32 -04:00
get "#{root_path}/:username/preferences/second-factor-backup" => "users#preferences", constraints: { username: RouteFormat.username }
delete "#{root_path}/:username/preferences/user_image" => "users#destroy_user_image", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/preferences/avatar/pick" => "users#pick_avatar", constraints: { username: RouteFormat.username }
2018-07-18 06:57:43 -04:00
put "#{root_path}/:username/preferences/avatar/select" => "users#select_avatar", constraints: { username: RouteFormat.username }
post "#{root_path}/:username/preferences/revoke-account" => "users#revoke_account", constraints: { username: RouteFormat.username }
post "#{root_path}/:username/preferences/revoke-auth-token" => "users#revoke_auth_token", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/staff-info" => "users#staff_info", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/summary" => "users#summary", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/notification_level" => "users#notification_level", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/invited" => "users#invited", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/invited/:filter" => "users#invited", constraints: { username: RouteFormat.username }
2017-03-30 22:04:00 -04:00
post "#{root_path}/action/send_activation_email" => "users#send_activation_email"
get "#{root_path}/:username/summary" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/activity/topics.rss" => "list#user_topics_feed", format: :rss, constraints: { username: RouteFormat.username }
get "#{root_path}/:username/activity.rss" => "posts#user_posts_feed", format: :rss, constraints: { username: RouteFormat.username }
get "#{root_path}/:username/activity.json" => "posts#user_posts_feed", format: :json, constraints: { username: RouteFormat.username }
get "#{root_path}/:username/activity" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/activity/:filter" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/badges" => "users#badges", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/bookmarks" => "users#bookmarks", constraints: { username: RouteFormat.username, format: /(json|ics)/ }
get "#{root_path}/:username/notifications" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/notifications/:filter" => "users#show", constraints: { username: RouteFormat.username }
delete "#{root_path}/:username" => "users#destroy", constraints: { username: RouteFormat.username }
2017-03-30 22:04:00 -04:00
get "#{root_path}/by-external/:external_id" => "users#show", constraints: { external_id: /[^\/]+/ }
get "#{root_path}/by-external/:external_provider/:external_id" => "users#show", constraints: { external_id: /[^\/]+/ }
get "#{root_path}/:username/flagged-posts" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/deleted-posts" => "users#show", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/topic-tracking-state" => "users#topic_tracking_state", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/profile-hidden" => "users#profile_hidden"
put "#{root_path}/:username/feature-topic" => "users#feature_topic", constraints: { username: RouteFormat.username }
put "#{root_path}/:username/clear-featured-topic" => "users#clear_featured_topic", constraints: { username: RouteFormat.username }
get "#{root_path}/:username/card.json" => "users#show_card", format: :json, constraints: { username: RouteFormat.username }
2017-03-30 22:04:00 -04:00
end
get "user-badges/:username.json" => "user_badges#username", constraints: { username: RouteFormat.username }, defaults: { format: :json }
get "user-badges/:username" => "user_badges#username", constraints: { username: RouteFormat.username }
post "user_avatar/:username/refresh_gravatar" => "user_avatars#refresh_gravatar", constraints: { username: RouteFormat.username }
get "letter_avatar/:username/:size/:version.png" => "user_avatars#show_letter", constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username, format: :png }
get "user_avatar/:hostname/:username/:size/:version.png" => "user_avatars#show", constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username, format: :png }
2013-12-23 18:50:36 -05:00
get "letter_avatar_proxy/:version/letter/:letter/:color/:size.png" => "user_avatars#show_proxy_letter", constraints: { format: :png }
get "svg-sprite/:hostname/svg-:theme_id-:version.js" => "svg_sprite#show", constraints: { hostname: /[\w\.-]+/, version: /\h{40}/, theme_id: /([0-9]+)?/, format: :js }
get "svg-sprite/search/:keyword" => "svg_sprite#search", format: false, constraints: { keyword: /[-a-z0-9\s\%]+/ }
get "svg-sprite/picker-search" => "svg_sprite#icon_picker_search", defaults: { format: :json }
get "svg-sprite/:hostname/icon(/:color)/:name.svg" => "svg_sprite#svg_icon", constraints: { hostname: /[\w\.-]+/, name: /[-a-z0-9\s\%]+/, color: /(\h{3}{1,2})/, format: :svg }
get "highlight-js/:hostname/:version.js" => "highlight_js#show", constraints: { hostname: /[\w\.-]+/, format: :js }
Upgrade to FontAwesome 5 (take two) (#6673) * Add missing icons to set * Revert FA5 revert This reverts commit 42572ff * use new SVG syntax in locales * Noscript page changes (remove login button, center "powered by" footer text) * Cast wider net for SVG icons in settings - include any _icon setting for SVG registry (offers better support for plugin settings) - let themes store multiple pipe-delimited icons in a setting - also replaces broken onebox image icon with SVG reference in cooked post processor * interpolate icons in locales * Fix composer whisper icon alignment * Add support for stacked icons * SECURITY: enforce hostname to match discourse hostname This ensures that the hostname rails uses for various helpers always matches the Discourse hostname * load SVG sprite with pre-initializers * FIX: enable caching on SVG sprites * PERF: use JSONP for SVG sprites so they are served from CDN This avoids needing to deal with CORS for loading of the SVG Note, added the svg- prefix to the filename so we can quickly tell in dev tools what the file is * Add missing SVG sprite JSONP script to CSP * Upgrade to FA 5.5.0 * Add support for all FA4.7 icons - adds complete frontend and backend for renamed FA4.7 icons - improves performance of SvgSprite.bundle and SvgSprite.all_icons * Fix group avatar flair preview - adds an endpoint at /svg-sprites/search/:keyword - adds frontend ajax call that pulls icon in avatar flair preview even when it is not in subset * Remove FA 4.7 font files
2018-11-26 16:49:57 -05:00
get "stylesheets/:name.css.map" => "stylesheets#show_source_map", constraints: { name: /[-a-z0-9_]+/ }
get "stylesheets/:name.css" => "stylesheets#show", constraints: { name: /[-a-z0-9_]+/ }
get "color-scheme-stylesheet/:id(/:theme_id)" => "stylesheets#color_scheme", constraints: { format: :json }
get "theme-javascripts/:digest.js" => "theme_javascripts#show", constraints: { digest: /\h{40}/ }
get "theme-javascripts/tests/:theme_id-:digest.js" => "theme_javascripts#show_tests"
post "uploads/lookup-metadata" => "uploads#metadata"
post "uploads" => "uploads#create"
post "uploads/lookup-urls" => "uploads#lookup_urls"
FEATURE: Initial implementation of direct S3 uploads with uppy and stubs (#13787) This adds a few different things to allow for direct S3 uploads using uppy. **These changes are still not the default.** There are hidden `enable_experimental_image_uploader` and `enable_direct_s3_uploads` settings that must be turned on for any of this code to be used, and even if they are turned on only the User Card Background for the user profile actually uses uppy-image-uploader. A new `ExternalUploadStub` model and database table is introduced in this pull request. This is used to keep track of uploads that are uploaded to a temporary location in S3 with the direct to S3 code, and they are eventually deleted a) when the direct upload is completed and b) after a certain time period of not being used. ### Starting a direct S3 upload When an S3 direct upload is initiated with uppy, we first request a presigned PUT URL from the new `generate-presigned-put` endpoint in `UploadsController`. This generates an S3 key in the `temp` folder inside the correct bucket path, along with any metadata from the clientside (e.g. the SHA1 checksum described below). This will also create an `ExternalUploadStub` and store the details of the temp object key and the file being uploaded. Once the clientside has this URL, uppy will upload the file direct to S3 using the presigned URL. Once the upload is complete we go to the next stage. ### Completing a direct S3 upload Once the upload to S3 is done we call the new `complete-external-upload` route with the unique identifier of the `ExternalUploadStub` created earlier. Only the user who made the stub can complete the external upload. One of two paths is followed via the `ExternalUploadManager`. 1. If the object in S3 is too large (currently 100mb defined by `ExternalUploadManager::DOWNLOAD_LIMIT`) we do not download and generate the SHA1 for that file. Instead we create the `Upload` record via `UploadCreator` and simply copy it to its final destination on S3 then delete the initial temp file. Several modifications to `UploadCreator` have been made to accommodate this. 2. If the object in S3 is small enough, we download it. When the temporary S3 file is downloaded, we compare the SHA1 checksum generated by the browser with the actual SHA1 checksum of the file generated by ruby. The browser SHA1 checksum is stored on the object in S3 with metadata, and is generated via the `UppyChecksum` plugin. Keep in mind that some browsers will not generate this due to compatibility or other issues. We then follow the normal `UploadCreator` path with one exception. To cut down on having to re-upload the file again, if there are no changes (such as resizing etc) to the file in `UploadCreator` we follow the same copy + delete temp path that we do for files that are too large. 3. Finally we return the serialized upload record back to the client There are several errors that could happen that are handled by `UploadsController` as well. Also in this PR is some refactoring of `displayErrorForUpload` to handle both uppy and jquery file uploader errors.
2021-07-27 18:42:25 -04:00
post "uploads/generate-presigned-put" => "uploads#generate_presigned_put"
post "uploads/complete-external-upload" => "uploads#complete_external_upload"
# used to download original images
get "uploads/:site/:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, sha: /\h{40}/, extension: /[a-z0-9\._]+/i }
get "uploads/short-url/:base62(.:extension)" => "uploads#show_short", constraints: { site: /\w+/, base62: /[a-zA-Z0-9]+/, extension: /[a-zA-Z0-9\._-]+/i }, as: :upload_short
# used to download attachments
get "uploads/:site/original/:tree:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, tree: /([a-z0-9]+\/)+/i, sha: /\h{40}/, extension: /[a-z0-9\._]+/i }
if Rails.env.test?
get "uploads/:site/test_:index/original/:tree:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, index: /\d+/, tree: /([a-z0-9]+\/)+/i, sha: /\h{40}/, extension: /[a-z0-9\._]+/i }
2020-06-04 22:49:31 -04:00
end
2015-05-20 08:55:42 -04:00
# used to download attachments (old route)
get "uploads/:site/:id/:sha" => "uploads#show", constraints: { site: /\w+/, id: /\d+/, sha: /\h{16}/, format: /.*/ }
get "secure-media-uploads/*path(.:extension)" => "uploads#show_secure", constraints: { extension: /[a-z0-9\._]+/i }
2020-06-04 22:49:31 -04:00
get "posts" => "posts#latest", id: "latest_posts", constraints: { format: /(json|rss)/ }
get "private-posts" => "posts#latest", id: "private_posts", constraints: { format: /(json|rss)/ }
2013-12-23 18:50:36 -05:00
get "posts/by_number/:topic_id/:post_number" => "posts#by_number"
get "posts/by-date/:topic_id/:date" => "posts#by_date"
2013-12-23 18:50:36 -05:00
get "posts/:id/reply-history" => "posts#reply_history"
get "posts/:id/reply-ids" => "posts#reply_ids"
get "posts/:id/reply-ids/all" => "posts#all_reply_ids"
get "posts/:username/deleted" => "posts#deleted_posts", constraints: { username: RouteFormat.username }
get "posts/:username/flagged" => "posts#flagged_posts", constraints: { username: RouteFormat.username }
2020-06-04 22:49:31 -04:00
%w{groups g}.each do |root_path|
resources :groups, id: RouteFormat.username, path: root_path do
get "posts.rss" => "groups#posts_feed", format: :rss
get "mentions.rss" => "groups#mentions_feed", format: :rss
2020-06-04 22:49:31 -04:00
get 'members'
get 'posts'
get 'mentions'
get 'counts'
get 'mentionable'
get 'messageable'
get 'logs' => 'groups#histories'
FEATURE: Improve group email settings UI (#13083) This overhauls the user interface for the group email settings management, aiming to make it a lot easier to test the settings entered and confirm they are correct before proceeding. We do this by forcing the user to test the settings before they can be saved to the database. It also includes some quality of life improvements around setting up IMAP and SMTP for our first supported provider, GMail. This PR does not remove the old group email config, that will come in a subsequent PR. This is related to https://meta.discourse.org/t/imap-support-for-group-inboxes/160588 so read that if you would like more backstory. ### UI Both site settings of `enable_imap` and `enable_smtp` must be true to test this. You must enable SMTP first to enable IMAP. You can prefill the SMTP settings with GMail configuration. To proceed with saving these settings you must test them, which is handled by the EmailSettingsValidator. If there is an issue with the configuration or credentials a meaningful error message should be shown. IMAP settings must also be validated when IMAP is enabled, before saving. When saving IMAP, we fetch the mailboxes for that account and populate them. This mailbox must be selected and saved for IMAP to work (the feature acts as though it is disabled until the mailbox is selected and saved): ### Database & Backend This adds several columns to the Groups table. The purpose of this change is to make it much more explicit that SMTP/IMAP is enabled for a group, rather than relying on settings not being null. Also included is an UPDATE query to backfill these columns. These columns are automatically filled when updating the group. For GMail, we now filter the mailboxes returned. This is so users cannot use a mailbox like Sent or Trash for syncing, which would generally be disastrous. There is a new group endpoint for testing email settings. This may be useful in the future for other places in our UI, at which point it can be extracted to a more generic endpoint or module to be included.
2021-05-27 19:28:18 -04:00
post 'test_email_settings'
2013-12-23 18:50:36 -05:00
collection do
get "check-name" => 'groups#check_name'
get 'custom/new' => 'groups#new', constraints: StaffConstraint.new
get "search" => "groups#search"
end
member do
2020-06-04 22:49:31 -04:00
%w{
activity
activity/:filter
2020-06-04 22:49:31 -04:00
requests
messages
messages/inbox
messages/archive
manage
manage/profile
manage/members
manage/membership
manage/interaction
manage/email
manage/categories
manage/tags
manage/logs
}.each do |path|
get path => 'groups#show'
end
get "permissions" => "groups#permissions"
put "members" => "groups#add_members"
put "join" => "groups#join"
delete "members" => "groups#remove_member"
delete "leave" => "groups#leave"
post "request_membership" => "groups#request_membership"
put "handle_membership_request" => "groups#handle_membership_request"
post "notifications" => "groups#set_notifications"
end
end
end
# aliases so old API code works
delete "admin/groups/:id/members" => "groups#remove_member", constraints: AdminConstraint.new
put "admin/groups/:id/members" => "groups#add_members", constraints: AdminConstraint.new
2020-06-04 22:49:31 -04:00
2013-02-05 14:16:51 -05:00
resources :posts do
Improving bookmarks part 1 (#8466) Note: All of this functionality is hidden behind a hidden, default false, site setting called `enable_bookmarks_with_reminders`. Also, any feedback on Ember code would be greatly appreciated! This is part 1 of the bookmark improvements. The next PR will address the backend logic to send reminder notifications for bookmarked posts to users. This PR adds the following functionality: * We are adding a new `bookmarks` table and `Bookmark` model to make the bookmarks a first-class citizen and to allow attaching reminders to them. * Posts now have a new button in their actions menu that has the icon of an actual book * Clicking the button opens the new bookmark modal. * Both name and the reminder type are optional. * If you close the modal without doing anything, the bookmark is saved with no reminder. * If you click the Cancel button, no bookmark is saved at all. * All of the reminder type tiles are dynamic and the times they show will be based on your user timezone set in your profile (this should already be set for you). * If for some reason a user does not have their timezone set they will not be able to set a reminder, but they will still be able to create a bookmark. * A bookmark can be deleted by clicking on the book icon again which will be red if the post is bookmarked. This PR does NOT do anything to migrate or change existing bookmarks in the form of `PostActions`, the two features live side-by-side here. Also this does nothing to the topic bookmarking.
2019-12-10 23:04:02 -05:00
delete "bookmark", to: "posts#destroy_bookmark"
2014-05-13 08:53:11 -04:00
put "wiki"
put "post_type"
put "rebake"
2014-09-22 12:55:13 -04:00
put "unhide"
put "locked"
put "notice"
2013-12-23 18:50:36 -05:00
get "replies"
get "revisions/latest" => "posts#latest_revision"
get "revisions/:revision" => "posts#revisions", constraints: { revision: /\d+/ }
put "revisions/:revision/hide" => "posts#hide_revision", constraints: { revision: /\d+/ }
put "revisions/:revision/show" => "posts#show_revision", constraints: { revision: /\d+/ }
put "revisions/:revision/revert" => "posts#revert", constraints: { revision: /\d+/ }
2013-12-23 18:50:36 -05:00
put "recover"
2013-02-05 14:16:51 -05:00
collection do
2013-12-23 18:50:36 -05:00
delete "destroy_many"
put "merge_posts"
2020-06-04 22:49:31 -04:00
end
2013-02-05 14:16:51 -05:00
end
resources :bookmarks, only: %i[create destroy update] do
put "toggle_pin"
end
Improving bookmarks part 1 (#8466) Note: All of this functionality is hidden behind a hidden, default false, site setting called `enable_bookmarks_with_reminders`. Also, any feedback on Ember code would be greatly appreciated! This is part 1 of the bookmark improvements. The next PR will address the backend logic to send reminder notifications for bookmarked posts to users. This PR adds the following functionality: * We are adding a new `bookmarks` table and `Bookmark` model to make the bookmarks a first-class citizen and to allow attaching reminders to them. * Posts now have a new button in their actions menu that has the icon of an actual book * Clicking the button opens the new bookmark modal. * Both name and the reminder type are optional. * If you close the modal without doing anything, the bookmark is saved with no reminder. * If you click the Cancel button, no bookmark is saved at all. * All of the reminder type tiles are dynamic and the times they show will be based on your user timezone set in your profile (this should already be set for you). * If for some reason a user does not have their timezone set they will not be able to set a reminder, but they will still be able to create a bookmark. * A bookmark can be deleted by clicking on the book icon again which will be red if the post is bookmarked. This PR does NOT do anything to migrate or change existing bookmarks in the form of `PostActions`, the two features live side-by-side here. Also this does nothing to the topic bookmarking.
2019-12-10 23:04:02 -05:00
resources :notifications, except: :show do
collection do
put 'mark-read' => 'notifications#mark_read'
# creating an alias cause the api was extended to mark a single notification
# this allows us to cleanly target it
put 'read' => 'notifications#mark_read'
2020-06-04 22:49:31 -04:00
end
end
match "/auth/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post]
get "/auth/:provider", to: "users/omniauth_callbacks#confirm_request"
match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: [:get, :post]
get "/associate/:token", to: "users/associate_accounts#connect_info", constraints: { token: /\h{32}/ }
post "/associate/:token", to: "users/associate_accounts#connect", constraints: { token: /\h{32}/ }
2013-02-05 14:16:51 -05:00
resources :clicks do
collection do
post "track"
2020-06-04 22:49:31 -04:00
end
2013-02-05 14:16:51 -05:00
end
2013-12-23 18:50:36 -05:00
get "excerpt" => "excerpt#show"
2013-02-05 14:16:51 -05:00
resources :post_action_users
resources :post_readers, only: %i[index]
2013-02-05 14:16:51 -05:00
resources :post_actions do
collection do
2013-12-23 18:50:36 -05:00
get "users"
post "defer_flags"
2020-06-04 22:49:31 -04:00
end
2013-02-05 14:16:51 -05:00
end
resources :user_actions
resources :badges, only: [:index]
get "/badges/:id(/:slug)" => "badges#show", constraints: { format: /(json|html|rss)/ }
resources :user_badges, only: [:index, :create, :destroy] do
put "toggle_favorite" => "user_badges#toggle_favorite", constraints: { format: :json }
end
2014-03-05 07:52:20 -05:00
get '/c', to: redirect(relative_url_root + 'categories')
resources :categories, except: [:show, :new, :edit]
2015-08-27 13:14:59 -04:00
post "categories/reorder" => "categories#reorder"
scope path: 'category/:category_id' do
post "/move" => "categories#move"
post "/notifications" => "categories#set_notifications"
put "/slug" => "categories#update_slug"
end
get "category/*path" => "categories#redirect"
get "categories_and_latest" => "categories#categories_and_latest"
get "categories_and_top" => "categories#categories_and_top"
get "c/:id/show" => "categories#show"
get "c/*category_slug/find_by_slug" => "categories#find_by_slug"
get "c/*category_slug/edit(/:tab)" => "categories#find_by_slug", constraints: { format: 'html' }
get "/new-category" => "categories#show", constraints: { format: 'html' }
get "c/*category_slug_path_with_id.rss" => "list#category_feed", format: :rss
scope path: 'c/*category_slug_path_with_id' do
get "/none" => "list#category_none_latest"
TopTopic.periods.each do |period|
get "/none/l/top/#{period}", to: redirect("/none/l/top?period=#{period}", status: 301)
get "/l/top/#{period}", to: redirect("/l/top?period=#{period}", status: 301)
end
Discourse.filters.each do |filter|
get "/none/l/#{filter}" => "list#category_none_#{filter}", as: "category_none_#{filter}"
get "/l/#{filter}" => "list#category_#{filter}", as: "category_#{filter}"
end
get "/all" => "list#category_default", as: "category_all", constraints: { format: 'html' }
get "/" => "list#category_default", as: "category_default"
end
get "hashtags" => "hashtags#show"
2014-01-13 19:02:14 -05:00
TopTopic.periods.each do |period|
get "top/#{period}.rss", to: redirect("top.rss?period=#{period}", status: 301)
get "top/#{period}.json", to: redirect("top.json?period=#{period}", status: 301)
get "top/#{period}", to: redirect("top?period=#{period}", status: 301)
2013-07-05 16:49:06 -04:00
end
2014-10-15 23:52:21 -04:00
Discourse.anonymous_filters.each do |filter|
get "#{filter}.rss" => "list##{filter}_feed", format: :rss
end
2013-12-23 18:50:36 -05:00
Discourse.filters.each do |filter|
get "#{filter}" => "list##{filter}"
end
2013-02-05 14:16:51 -05:00
2015-04-03 16:55:32 -04:00
get "search/query" => "search#query"
get "search" => "search#show"
post "search/click" => "search#click"
2020-06-04 22:49:31 -04:00
2013-02-05 14:16:51 -05:00
# Topics resource
2013-12-23 18:50:36 -05:00
get "t/:id" => "topics#show"
2014-01-13 19:02:14 -05:00
put "t/:id" => "topics#update"
delete "t/:id" => "topics#destroy"
put "t/:id/archive-message" => "topics#archive_message"
put "t/:id/move-to-inbox" => "topics#move_to_inbox"
put "t/:id/convert-topic/:type" => "topics#convert_topic"
put "t/:id/publish" => "topics#publish"
put "t/:id/shared-draft" => "topics#update_shared_draft"
put "t/:id/reset-bump-date" => "topics#reset_bump_date"
put "topics/bulk"
2014-03-03 15:46:38 -05:00
put "topics/reset-new" => 'topics#reset_new'
2013-12-23 18:50:36 -05:00
post "topics/timings"
2020-06-04 22:49:31 -04:00
get 'topics/similar_to' => 'similar_topics#index'
resources :similar_topics
2020-06-04 22:49:31 -04:00
get "topics/feature_stats"
2020-06-04 22:49:31 -04:00
2018-02-13 15:46:25 -05:00
scope "/topics", username: RouteFormat.username do
get "created-by/:username" => "list#topics_by", as: "topics_by", defaults: { format: :json }
get "private-messages/:username" => "list#private_messages", as: "topics_private_messages", defaults: { format: :json }
get "private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", defaults: { format: :json }
get "private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive", defaults: { format: :json }
get "private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", defaults: { format: :json }
get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", as: "topics_private_messages_tag", defaults: { format: :json }
get "private-messages-warnings/:username" => "list#private_messages_warnings", as: "topics_private_messages_warnings", defaults: { format: :json }
get "groups/:group_name" => "list#group_topics", as: "group_topics", group_name: RouteFormat.username
2020-06-04 22:49:31 -04:00
2018-02-13 15:46:25 -05:00
scope "/private-messages-group/:username", group_name: RouteFormat.username do
get ":group_name.json" => "list#private_messages_group", as: "topics_private_messages_group"
get ":group_name/archive.json" => "list#private_messages_group_archive", as: "topics_private_messages_group_archive"
2020-06-04 22:49:31 -04:00
end
2018-02-13 15:46:25 -05:00
end
get 'embed/topics' => 'embed#topics'
2014-01-03 12:52:24 -05:00
get 'embed/comments' => 'embed#comments'
get 'embed/count' => 'embed#count'
get 'embed/info' => 'embed#info'
2020-06-04 22:49:31 -04:00
get "new-topic" => "list#latest"
get "new-message" => "list#latest"
2020-06-04 22:49:31 -04:00
# Topic routes
get "t/id_for/:slug" => "topics#id_for_slug"
get "t/:slug/:topic_id/print" => "topics#show", format: :html, print: true, constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
get "t/:slug/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ }
get "t/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ }
get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", constraints: { topic_id: /\d+/ }
get "t/:slug/:topic_id/summary" => "topics#show", defaults: { summary: true }, constraints: { topic_id: /\d+/ }
get "t/:topic_id/summary" => "topics#show", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
put "t/:slug/:topic_id" => "topics#update", constraints: { topic_id: /\d+/ }
put "t/:slug/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ }
put "t/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ }
put "t/:slug/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ }
put "t/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ }
put "t/:topic_id/clear-pin" => "topics#clear_pin", constraints: { topic_id: /\d+/ }
put "t/:topic_id/re-pin" => "topics#re_pin", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
put "t/:topic_id/mute" => "topics#mute", constraints: { topic_id: /\d+/ }
put "t/:topic_id/unmute" => "topics#unmute", constraints: { topic_id: /\d+/ }
post "t/:topic_id/timer" => "topics#timer", constraints: { topic_id: /\d+/ }
2014-06-16 12:28:07 -04:00
put "t/:topic_id/make-banner" => "topics#make_banner", constraints: { topic_id: /\d+/ }
put "t/:topic_id/remove-banner" => "topics#remove_banner", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", constraints: { topic_id: /\d+/ }
put "t/:topic_id/remove-allowed-group" => "topics#remove_allowed_group", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
put "t/:topic_id/recover" => "topics#recover", constraints: { topic_id: /\d+/ }
get "t/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ }
get "t/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
get "t/:slug/:topic_id.rss" => "topics#feed", format: :rss, constraints: { topic_id: /\d+/ }
get "t/:slug/:topic_id" => "topics#show", constraints: { topic_id: /\d+/ }
get "t/:slug/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ }
get "t/:slug/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ }
get "t/:topic_id/posts" => "topics#posts", constraints: { topic_id: /\d+/ }, format: :json
get "t/:topic_id/post_ids" => "topics#post_ids", constraints: { topic_id: /\d+/ }, format: :json
get "t/:topic_id/excerpts" => "topics#excerpts", constraints: { topic_id: /\d+/ }, format: :json
2013-12-23 18:50:36 -05:00
post "t/:topic_id/timings" => "topics#timings", constraints: { topic_id: /\d+/ }
post "t/:topic_id/invite" => "topics#invite", constraints: { topic_id: /\d+/ }
post "t/:topic_id/invite-group" => "topics#invite_group", constraints: { topic_id: /\d+/ }
post "t/:topic_id/invite-notify" => "topics#invite_notify", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
post "t/:topic_id/move-posts" => "topics#move_posts", constraints: { topic_id: /\d+/ }
post "t/:topic_id/merge-topic" => "topics#merge_topic", constraints: { topic_id: /\d+/ }
post "t/:topic_id/change-owner" => "topics#change_post_owners", constraints: { topic_id: /\d+/ }
put "t/:topic_id/change-timestamp" => "topics#change_timestamps", constraints: { topic_id: /\d+/ }
2013-12-23 18:50:36 -05:00
delete "t/:topic_id/timings" => "topics#destroy_timings", constraints: { topic_id: /\d+/ }
2015-01-12 06:10:15 -05:00
put "t/:topic_id/bookmark" => "topics#bookmark", constraints: { topic_id: /\d+/ }
put "t/:topic_id/remove_bookmarks" => "topics#remove_bookmarks", constraints: { topic_id: /\d+/ }
put "t/:topic_id/tags" => "topics#update_tags", constraints: { topic_id: /\d+/ }
put "t/:topic_id/slow_mode" => "topics#set_slow_mode", constraints: { topic_id: /\d+/ }
2020-06-04 22:49:31 -04:00
2013-12-23 18:50:36 -05:00
post "t/:topic_id/notifications" => "topics#set_notifications" , constraints: { topic_id: /\d+/ }
2020-06-04 22:49:31 -04:00
get "p/:post_id(/:user_id)" => "posts#short_link"
get "/posts/:id/cooked" => "posts#cooked"
2014-04-01 17:45:16 -04:00
get "/posts/:id/expand-embed" => "posts#expand_embed"
get "/posts/:id/raw" => "posts#markdown_id"
2014-10-17 15:18:29 -04:00
get "/posts/:id/raw-email" => "posts#raw_email"
get "raw/:topic_id(/:post_number)" => "posts#markdown_num"
2020-06-04 22:49:31 -04:00
resources :invites, except: [:show]
get "/invites/:id" => "invites#show", constraints: { format: :html }
put "/invites/:id" => "invites#update"
2020-06-04 22:49:31 -04:00
2016-12-04 11:06:35 -05:00
post "invites/upload_csv" => "invites#upload_csv"
post "invites/destroy-all-expired" => "invites#destroy_all_expired"
2014-10-06 14:48:56 -04:00
post "invites/reinvite" => "invites#resend_invite"
post "invites/reinvite-all" => "invites#resend_all_invites"
2013-12-23 18:50:36 -05:00
delete "invites" => "invites#destroy"
put "invites/show/:id" => "invites#perform_accept_invitation", as: 'perform_accept_invite'
get "invites/retrieve" => "invites#retrieve"
2020-06-04 22:49:31 -04:00
2014-12-22 11:17:04 -05:00
resources :export_csv do
collection do
post "export_entity" => "export_csv#export_entity"
2020-06-04 22:49:31 -04:00
end
2014-12-22 11:17:04 -05:00
end
2013-12-23 18:50:36 -05:00
get "onebox" => "onebox#show"
get "inline-onebox" => "inline_onebox#show"
2013-02-05 14:16:51 -05:00
2014-06-16 14:25:33 -04:00
get "exception" => "list#latest"
2013-02-05 14:16:51 -05:00
2013-12-23 18:50:36 -05:00
get "message-bus/poll" => "message_bus#poll"
2013-02-05 14:16:51 -05:00
resources :drafts, only: [:index]
2013-12-23 18:50:36 -05:00
get "draft" => "draft#show"
post "draft" => "draft#update"
delete "draft" => "draft#destroy"
2013-02-05 14:16:51 -05:00
if service_worker_asset = Rails.application.assets_manifest.assets['service-worker.js']
# https://developers.google.com/web/fundamentals/codelabs/debugging-service-workers/
# Normally the browser will wait until a user closes all tabs that contain the
# current site before updating to a new Service Worker.
# Support the old Service Worker path to avoid routing error filling up the
# logs.
get "/service-worker.js" => "static#service_worker_asset", format: :js
get service_worker_asset => "static#service_worker_asset", format: :js
elsif Rails.env.development?
get "/service-worker.js" => "static#service_worker_asset", format: :js
end
get "cdn_asset/:site/*path" => "static#cdn_asset", format: false, constraints: { format: /.*/ }
get "brotli_asset/*path" => "static#brotli_asset", format: false, constraints: { format: /.*/ }
2020-06-04 22:49:31 -04:00
get "favicon/proxied" => "static#favicon", format: false
2020-06-04 22:49:31 -04:00
2013-12-23 18:50:36 -05:00
get "robots.txt" => "robots_txt#index"
get "robots-builder.json" => "robots_txt#builder"
get "offline.html" => "offline#index"
get "manifest.webmanifest" => "metadata#manifest", as: :manifest
get "manifest.json" => "metadata#manifest"
get ".well-known/assetlinks.json" => "metadata#app_association_android"
get "apple-app-site-association" => "metadata#app_association_ios", format: false
get "opensearch" => "metadata#opensearch", constraints: { format: :xml }
2020-06-04 22:49:31 -04:00
scope '/tag/:tag_id' do
constraints format: :json do
get '/' => 'tags#show', as: 'tag_show'
get '/info' => 'tags#info'
get '/notifications' => 'tags#notifications'
put '/notifications' => 'tags#update_notifications'
put '/' => 'tags#update'
delete '/' => 'tags#destroy'
post '/synonyms' => 'tags#create_synonyms'
delete '/synonyms/:synonym_id' => 'tags#destroy_synonym'
Discourse.filters.each do |filter|
get "/l/#{filter}" => "tags#show_#{filter}", as: "tag_show_#{filter}"
2020-06-04 22:49:31 -04:00
end
end
constraints format: :rss do
get '/' => 'tags#tag_feed'
2020-06-04 22:49:31 -04:00
end
end
scope "/tags" do
get '/' => 'tags#index'
get '/filter/list' => 'tags#index'
get '/filter/search' => 'tags#search'
get '/personal_messages/:username' => 'tags#personal_messages', constraints: { username: RouteFormat.username }
2018-10-15 04:12:54 -04:00
post '/upload' => 'tags#upload'
get '/unused' => 'tags#list_unused'
delete '/unused' => 'tags#destroy_unused'
2020-06-04 22:49:31 -04:00
constraints(tag_id: /[^\/]+?/, format: /json|rss/) do
scope path: '/c/*category_slug_path_with_id' do
Discourse.filters.each do |filter|
get "/none/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_none_show_#{filter}", defaults: { no_subcategories: true }
end
get '/none/:tag_id' => 'tags#show', as: 'tag_category_none_show', defaults: { no_subcategories: true }
Discourse.filters.each do |filter|
get "/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_show_#{filter}"
2020-06-04 22:49:31 -04:00
end
get '/:tag_id' => 'tags#show', as: 'tag_category_show'
end
get '/intersection/:tag_id/*additional_tag_ids' => 'tags#show', as: 'tag_intersection'
end
get '*tag_id', to: redirect(relative_url_root + 'tag/%{tag_id}')
end
resources :tag_groups, constraints: StaffConstraint.new, except: [:edit]
get '/tag_groups/filter/search' => 'tag_groups#search', format: :json
2013-12-23 18:50:36 -05:00
Discourse.filters.each do |filter|
root to: "list##{filter}", constraints: HomePageConstraint.new("#{filter}"), as: "list_#{filter}"
end
# special case for categories
root to: "categories#index", constraints: HomePageConstraint.new("categories"), as: "categories_index"
2020-06-04 22:49:31 -04:00
root to: 'finish_installation#index', constraints: HomePageConstraint.new("finish_installation"), as: 'installation_redirect'
2020-06-04 22:49:31 -04:00
get "/user-api-key/new" => "user_api_keys#new"
post "/user-api-key" => "user_api_keys#create"
post "/user-api-key/revoke" => "user_api_keys#revoke"
post "/user-api-key/undo-revoke" => "user_api_keys#undo_revoke"
get "/user-api-key/otp" => "user_api_keys#otp"
post "/user-api-key/otp" => "user_api_keys#create_otp"
2020-06-04 22:49:31 -04:00
get "/safe-mode" => "safe_mode#index"
post "/safe-mode" => "safe_mode#enter", as: "safe_mode_enter"
2020-06-04 22:49:31 -04:00
unless Rails.env.production?
get "/qunit" => "qunit#index"
get "/wizard/qunit" => "wizard#qunit"
end
get "/theme-qunit" => "qunit#theme"
post "/push_notifications/subscribe" => "push_notification#subscribe"
post "/push_notifications/unsubscribe" => "push_notification#unsubscribe"
resources :csp_reports, only: [:create]
get "/permalink-check", to: 'permalinks#check'
2020-12-18 10:03:51 -05:00
post "/do-not-disturb" => "do_not_disturb#create"
delete "/do-not-disturb" => "do_not_disturb#destroy"
get "*url", to: 'permalinks#show', constraints: PermalinkConstraint.new
end
2013-02-05 14:16:51 -05:00
end