PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/config/routes.rb

https://bitbucket.org/bitworkvn/cs_discourse
Ruby | 805 lines | 667 code | 119 blank | 19 comment | 5 complexity | dd52055db3fa323fd7c0522e0112589f MD5 | raw file
  1. require "sidekiq/web"
  2. require_dependency "scheduler/web"
  3. require_dependency "admin_constraint"
  4. require_dependency "staff_constraint"
  5. require_dependency "homepage_constraint"
  6. require_dependency "permalink_constraint"
  7. # The following constants have been replaced with `RouteFormat` and are deprecated.
  8. USERNAME_ROUTE_FORMAT = /[\w.\-]+?/ unless defined? USERNAME_ROUTE_FORMAT
  9. BACKUP_ROUTE_FORMAT = /.+\.(sql\.gz|tar\.gz|tgz)/i unless defined? BACKUP_ROUTE_FORMAT
  10. Discourse::Application.routes.draw do
  11. relative_url_root = (defined?(Rails.configuration.relative_url_root) && Rails.configuration.relative_url_root) ? Rails.configuration.relative_url_root + '/' : '/'
  12. match "/404", to: "exceptions#not_found", via: [:get, :post]
  13. get "/404-body" => "exceptions#not_found_body"
  14. post "webhooks/mailgun" => "webhooks#mailgun"
  15. post "webhooks/sendgrid" => "webhooks#sendgrid"
  16. post "webhooks/mailjet" => "webhooks#mailjet"
  17. post "webhooks/mandrill" => "webhooks#mandrill"
  18. post "webhooks/sparkpost" => "webhooks#sparkpost"
  19. if Rails.env.development?
  20. mount Sidekiq::Web => "/sidekiq"
  21. mount Logster::Web => "/logs"
  22. else
  23. # only allow sidekiq in master site
  24. mount Sidekiq::Web => "/sidekiq", constraints: AdminConstraint.new(require_master: true)
  25. mount Logster::Web => "/logs", constraints: AdminConstraint.new
  26. end
  27. resources :about do
  28. collection do
  29. get "live_post_counts"
  30. end
  31. end
  32. get "finish-installation" => "finish_installation#index"
  33. get "finish-installation/register" => "finish_installation#register"
  34. post "finish-installation/register" => "finish_installation#register"
  35. get "finish-installation/confirm-email" => "finish_installation#confirm_email"
  36. put "finish-installation/resend-email" => "finish_installation#resend_email"
  37. resources :directory_items
  38. get "site" => "site#site"
  39. namespace :site do
  40. get "settings"
  41. get "custom_html"
  42. get "banner"
  43. get "emoji"
  44. end
  45. get "site/basic-info" => 'site#basic_info'
  46. get "site/statistics" => 'site#statistics'
  47. get "srv/status" => "forums#status"
  48. get "wizard" => "wizard#index"
  49. get "wizard/qunit" => "wizard#qunit"
  50. get 'wizard/steps' => 'steps#index'
  51. get 'wizard/steps/:id' => "wizard#index"
  52. put 'wizard/steps/:id' => "steps#update"
  53. namespace :admin, constraints: StaffConstraint.new do
  54. get "" => "admin#index"
  55. get 'plugins' => 'plugins#index'
  56. resources :site_settings, constraints: AdminConstraint.new do
  57. collection do
  58. get "category/:id" => "site_settings#index"
  59. end
  60. end
  61. get "reports/:type" => "reports#show"
  62. resources :groups, constraints: AdminConstraint.new do
  63. collection do
  64. get 'bulk'
  65. get 'bulk-complete' => 'groups#bulk'
  66. put 'bulk' => 'groups#bulk_perform'
  67. end
  68. member do
  69. put "owners" => "groups#add_owners"
  70. delete "owners" => "groups#remove_owner"
  71. end
  72. end
  73. get "groups/:type" => "groups#show", constraints: AdminConstraint.new
  74. get "groups/:type/:id" => "groups#show", constraints: AdminConstraint.new
  75. get "moderation_history" => "moderation_history#index"
  76. resources :users, id: RouteFormat.username, except: [:show] do
  77. collection do
  78. get "list" => "users#index"
  79. get "list/:query" => "users#index"
  80. get "ip-info" => "users#ip_info"
  81. delete "delete-others-with-same-ip" => "users#delete_other_accounts_with_same_ip"
  82. get "total-others-with-same-ip" => "users#total_other_accounts_with_same_ip"
  83. put "approve-bulk" => "users#approve_bulk"
  84. delete "reject-bulk" => "users#reject_bulk"
  85. end
  86. put "suspend"
  87. put "delete_all_posts"
  88. put "unsuspend"
  89. put "revoke_admin", constraints: AdminConstraint.new
  90. put "grant_admin", constraints: AdminConstraint.new
  91. post "generate_api_key", constraints: AdminConstraint.new
  92. delete "revoke_api_key", constraints: AdminConstraint.new
  93. put "revoke_moderation", constraints: AdminConstraint.new
  94. put "grant_moderation", constraints: AdminConstraint.new
  95. put "approve"
  96. post "refresh_browsers", constraints: AdminConstraint.new
  97. post "log_out", constraints: AdminConstraint.new
  98. put "activate"
  99. put "deactivate"
  100. put "silence"
  101. put "unsilence"
  102. put "trust_level"
  103. put "trust_level_lock"
  104. put "primary_group"
  105. post "groups" => "users#add_group", constraints: AdminConstraint.new
  106. delete "groups/:group_id" => "users#remove_group", constraints: AdminConstraint.new
  107. get "badges"
  108. get "leader_requirements" => "users#tl3_requirements"
  109. get "tl3_requirements"
  110. put "anonymize"
  111. post "reset_bounce_score"
  112. put "disable_second_factor"
  113. end
  114. get "users/:id.json" => 'users#show', defaults: { format: 'json' }
  115. get 'users/:id/:username' => 'users#show', constraints: { username: RouteFormat.username }
  116. get 'users/:id/:username/badges' => 'users#show'
  117. get 'users/:id/:username/tl3_requirements' => 'users#show'
  118. post "users/sync_sso" => "users#sync_sso", constraints: AdminConstraint.new
  119. post "users/invite_admin" => "users#invite_admin", constraints: AdminConstraint.new
  120. resources :impersonate, constraints: AdminConstraint.new
  121. resources :email, constraints: AdminConstraint.new do
  122. collection do
  123. post "test"
  124. get "sent"
  125. get "skipped"
  126. get "bounced"
  127. get "received"
  128. get "rejected"
  129. get "/incoming/:id/raw" => "email#raw_email"
  130. get "/incoming/:id" => "email#incoming"
  131. get "/incoming_from_bounced/:id" => "email#incoming_from_bounced"
  132. get "preview-digest" => "email#preview_digest"
  133. get "send-digest" => "email#send_digest"
  134. get "smtp_should_reject"
  135. post "handle_mail"
  136. end
  137. end
  138. scope "/logs" do
  139. resources :staff_action_logs, only: [:index]
  140. get 'staff_action_logs/:id/diff' => 'staff_action_logs#diff'
  141. resources :screened_emails, only: [:index, :destroy]
  142. resources :screened_ip_addresses, only: [:index, :create, :update, :destroy] do
  143. collection do
  144. post "roll_up"
  145. end
  146. end
  147. resources :screened_urls, only: [:index]
  148. resources :watched_words, only: [:index, :create, :update, :destroy] do
  149. collection do
  150. get "action/:id" => "watched_words#index"
  151. end
  152. end
  153. post "watched_words/upload" => "watched_words#upload"
  154. resources :search_logs, only: [:index]
  155. get 'search_logs/term/:term' => 'search_logs#term'
  156. end
  157. get "/logs" => "staff_action_logs#index"
  158. get "customize" => "color_schemes#index", constraints: AdminConstraint.new
  159. get "customize/themes" => "themes#index", constraints: AdminConstraint.new
  160. get "customize/colors" => "color_schemes#index", constraints: AdminConstraint.new
  161. get "customize/colors/:id" => "color_schemes#index", constraints: AdminConstraint.new
  162. get "customize/permalinks" => "permalinks#index", constraints: AdminConstraint.new
  163. get "customize/embedding" => "embedding#show", constraints: AdminConstraint.new
  164. put "customize/embedding" => "embedding#update", constraints: AdminConstraint.new
  165. get "flags" => "flags#index"
  166. get "flags/:filter" => "flags#index", as: 'flags_filtered'
  167. get "flags/topics/:topic_id" => "flags#index"
  168. post "flags/agree/:id" => "flags#agree"
  169. post "flags/disagree/:id" => "flags#disagree"
  170. post "flags/defer/:id" => "flags#defer"
  171. resources :flagged_topics, constraints: StaffConstraint.new
  172. resources :themes, constraints: AdminConstraint.new
  173. post "themes/import" => "themes#import"
  174. post "themes/upload_asset" => "themes#upload_asset"
  175. post "themes/generate_key_pair" => "themes#generate_key_pair"
  176. get "themes/:id/preview" => "themes#preview"
  177. scope "/customize", constraints: AdminConstraint.new do
  178. resources :user_fields, constraints: AdminConstraint.new
  179. resources :emojis, constraints: AdminConstraint.new
  180. get 'themes/:id/:target/:field_name/edit' => 'themes#index'
  181. get 'themes/:id' => 'themes#index'
  182. # They have periods in their URLs often:
  183. get 'site_texts' => 'site_texts#index'
  184. get 'site_texts/(:id)' => 'site_texts#show', constraints: { id: /[\w.\-\+]+/i }
  185. put 'site_texts/(:id)' => 'site_texts#update', constraints: { id: /[\w.\-\+]+/i }
  186. delete 'site_texts/(:id)' => 'site_texts#revert', constraints: { id: /[\w.\-\+]+/i }
  187. get 'email_templates' => 'email_templates#index'
  188. get 'email_templates/(:id)' => 'email_templates#show', constraints: { id: /[0-9a-z_.]+/ }
  189. put 'email_templates/(:id)' => 'email_templates#update', constraints: { id: /[0-9a-z_.]+/ }
  190. delete 'email_templates/(:id)' => 'email_templates#revert', constraints: { id: /[0-9a-z_.]+/ }
  191. end
  192. resources :embeddable_hosts, constraints: AdminConstraint.new
  193. resources :color_schemes, constraints: AdminConstraint.new
  194. resources :permalinks, constraints: AdminConstraint.new
  195. get "version_check" => "versions#show"
  196. get "dashboard-next" => "dashboard_next#index"
  197. resources :dashboard, only: [:index] do
  198. collection do
  199. get "problems"
  200. end
  201. end
  202. resources :api, only: [:index], constraints: AdminConstraint.new do
  203. collection do
  204. get "keys" => "api#index"
  205. post "key" => "api#create_master_key"
  206. put "key" => "api#regenerate_key"
  207. delete "key" => "api#revoke_key"
  208. resources :web_hooks
  209. get 'web_hook_events/:id' => 'web_hooks#list_events', as: :web_hook_events
  210. get 'web_hooks/:id/events' => 'web_hooks#list_events'
  211. get 'web_hooks/:id/events/bulk' => 'web_hooks#bulk_events'
  212. post 'web_hooks/:web_hook_id/events/:event_id/redeliver' => 'web_hooks#redeliver_event'
  213. post 'web_hooks/:id/ping' => 'web_hooks#ping'
  214. end
  215. end
  216. resources :backups, only: [:index, :create], constraints: AdminConstraint.new do
  217. member do
  218. get "" => "backups#show", constraints: { id: RouteFormat.backup }
  219. put "" => "backups#email", constraints: { id: RouteFormat.backup }
  220. delete "" => "backups#destroy", constraints: { id: RouteFormat.backup }
  221. post "restore" => "backups#restore", constraints: { id: RouteFormat.backup }
  222. end
  223. collection do
  224. get "logs" => "backups#logs"
  225. get "status" => "backups#status"
  226. delete "cancel" => "backups#cancel"
  227. post "rollback" => "backups#rollback"
  228. put "readonly" => "backups#readonly"
  229. get "upload" => "backups#check_backup_chunk"
  230. post "upload" => "backups#upload_backup_chunk"
  231. end
  232. end
  233. resources :badges, constraints: AdminConstraint.new do
  234. collection do
  235. get "types" => "badges#badge_types"
  236. post "badge_groupings" => "badges#save_badge_groupings"
  237. post "preview" => "badges#preview"
  238. end
  239. end
  240. get "memory_stats" => "diagnostics#memory_stats", constraints: AdminConstraint.new
  241. get "dump_heap" => "diagnostics#dump_heap", constraints: AdminConstraint.new
  242. get "dump_statement_cache" => "diagnostics#dump_statement_cache", constraints: AdminConstraint.new
  243. end # admin namespace
  244. get "email_preferences" => "email#preferences_redirect", :as => "email_preferences_redirect"
  245. get "email/unsubscribe/:key" => "email#unsubscribe", as: "email_unsubscribe"
  246. get "email/unsubscribed" => "email#unsubscribed", as: "email_unsubscribed"
  247. post "email/unsubscribe/:key" => "email#perform_unsubscribe", as: "email_perform_unsubscribe"
  248. get "extra-locales/:bundle" => "extra_locales#show"
  249. resources :session, id: RouteFormat.username, only: [:create, :destroy, :become] do
  250. if !Rails.env.production?
  251. get 'become'
  252. end
  253. collection do
  254. post "forgot_password"
  255. end
  256. end
  257. get "session/sso" => "session#sso"
  258. get "session/sso_login" => "session#sso_login"
  259. get "session/sso_provider" => "session#sso_provider"
  260. get "session/current" => "session#current"
  261. get "session/csrf" => "session#csrf"
  262. get "session/email-login/:token" => "session#email_login"
  263. post "session/email-login/:token" => "session#email_login"
  264. get "composer_messages" => "composer_messages#index"
  265. post "composer/parse_html" => "composer#parse_html"
  266. resources :static
  267. post "login" => "static#enter", constraints: { format: /(json|html)/ }
  268. get "login" => "static#show", id: "login", constraints: { format: /(json|html)/ }
  269. get "password-reset" => "static#show", id: "password_reset", constraints: { format: /(json|html)/ }
  270. get "faq" => "static#show", id: "faq", constraints: { format: /(json|html)/ }
  271. get "guidelines" => "static#show", id: "guidelines", as: 'guidelines', constraints: { format: /(json|html)/ }
  272. get "tos" => "static#show", id: "tos", as: 'tos', constraints: { format: /(json|html)/ }
  273. get "privacy" => "static#show", id: "privacy", as: 'privacy', constraints: { format: /(json|html)/ }
  274. get "signup" => "static#show", id: "signup", constraints: { format: /(json|html)/ }
  275. get "login-preferences" => "static#show", id: "login", constraints: { format: /(json|html)/ }
  276. get "my/*path", to: 'users#my_redirect'
  277. get "user_preferences" => "users#user_preferences_redirect"
  278. %w{users u}.each_with_index do |root_path, index|
  279. get "#{root_path}" => "users#index", constraints: { format: 'html' }
  280. resources :users, except: [:index, :new, :show, :update, :destroy], path: root_path do
  281. collection do
  282. get "check_username"
  283. get "is_local_username"
  284. end
  285. end
  286. post "#{root_path}/second_factors" => "users#create_second_factor"
  287. put "#{root_path}/second_factor" => "users#update_second_factor"
  288. put "#{root_path}/update-activation-email" => "users#update_activation_email"
  289. get "#{root_path}/hp" => "users#get_honeypot_value"
  290. post "#{root_path}/email-login" => "users#email_login"
  291. get "#{root_path}/admin-login" => "users#admin_login"
  292. put "#{root_path}/admin-login" => "users#admin_login"
  293. get "#{root_path}/admin-login/:token" => "users#admin_login"
  294. put "#{root_path}/admin-login/:token" => "users#admin_login"
  295. post "#{root_path}/toggle-anon" => "users#toggle_anon"
  296. post "#{root_path}/read-faq" => "users#read_faq"
  297. get "#{root_path}/search/users" => "users#search_users"
  298. get({ "#{root_path}/account-created/" => "users#account_created" }.merge(index == 1 ? { as: :users_account_created } : { as: :old_account_created }))
  299. get "#{root_path}/account-created/resent" => "users#account_created"
  300. get "#{root_path}/account-created/edit-email" => "users#account_created"
  301. get({ "#{root_path}/password-reset/:token" => "users#password_reset" }.merge(index == 1 ? { as: :password_reset_token } : {}))
  302. get "#{root_path}/confirm-email-token/:token" => "users#confirm_email_token", constraints: { format: 'json' }
  303. put "#{root_path}/password-reset/:token" => "users#password_reset"
  304. get "#{root_path}/activate-account/:token" => "users#activate_account"
  305. put({ "#{root_path}/activate-account/:token" => "users#perform_account_activation" }.merge(index == 1 ? { as: 'perform_activate_account' } : {}))
  306. get "#{root_path}/authorize-email/:token" => "users_email#confirm"
  307. put "#{root_path}/authorize-email/:token" => "users_email#confirm"
  308. get({
  309. "#{root_path}/confirm-admin/:token" => "users#confirm_admin",
  310. constraints: { token: /[0-9a-f]+/ }
  311. }.merge(index == 1 ? { as: 'confirm_admin' } : {}))
  312. post "#{root_path}/confirm-admin/:token" => "users#confirm_admin", constraints: { token: /[0-9a-f]+/ }
  313. get "#{root_path}/:username/private-messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
  314. get "#{root_path}/:username/private-messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
  315. get "#{root_path}/:username/messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
  316. get "#{root_path}/:username/messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username }
  317. get "#{root_path}/:username/messages/group/:group_name" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username }
  318. get "#{root_path}/:username/messages/group/:group_name/archive" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username }
  319. get "#{root_path}/:username/messages/tags/:tag_id" => "user_actions#private_messages", constraints: StaffConstraint.new
  320. get "#{root_path}/:username.json" => "users#show", constraints: { username: RouteFormat.username }, defaults: { format: :json }
  321. get({ "#{root_path}/:username" => "users#show", constraints: { username: RouteFormat.username, format: /(json|html)/ } }.merge(index == 1 ? { as: 'user' } : {}))
  322. put "#{root_path}/:username" => "users#update", constraints: { username: RouteFormat.username }, defaults: { format: :json }
  323. get "#{root_path}/:username/emails" => "users#check_emails", constraints: { username: RouteFormat.username }
  324. get({ "#{root_path}/:username/preferences" => "users#preferences", constraints: { username: RouteFormat.username } }.merge(index == 1 ? { as: :email_preferences } : {}))
  325. get "#{root_path}/:username/preferences/email" => "users_email#index", constraints: { username: RouteFormat.username }
  326. get "#{root_path}/:username/preferences/account" => "users#preferences", constraints: { username: RouteFormat.username }
  327. get "#{root_path}/:username/preferences/profile" => "users#preferences", constraints: { username: RouteFormat.username }
  328. get "#{root_path}/:username/preferences/emails" => "users#preferences", constraints: { username: RouteFormat.username }
  329. get "#{root_path}/:username/preferences/notifications" => "users#preferences", constraints: { username: RouteFormat.username }
  330. get "#{root_path}/:username/preferences/categories" => "users#preferences", constraints: { username: RouteFormat.username }
  331. get "#{root_path}/:username/preferences/tags" => "users#preferences", constraints: { username: RouteFormat.username }
  332. get "#{root_path}/:username/preferences/interface" => "users#preferences", constraints: { username: RouteFormat.username }
  333. get "#{root_path}/:username/preferences/apps" => "users#preferences", constraints: { username: RouteFormat.username }
  334. put "#{root_path}/:username/preferences/email" => "users_email#update", constraints: { username: RouteFormat.username }
  335. get "#{root_path}/:username/preferences/about-me" => "users#preferences", constraints: { username: RouteFormat.username }
  336. get "#{root_path}/:username/preferences/badge_title" => "users#preferences", constraints: { username: RouteFormat.username }
  337. put "#{root_path}/:username/preferences/badge_title" => "users#badge_title", constraints: { username: RouteFormat.username }
  338. get "#{root_path}/:username/preferences/username" => "users#preferences", constraints: { username: RouteFormat.username }
  339. put "#{root_path}/:username/preferences/username" => "users#username", constraints: { username: RouteFormat.username }
  340. get "#{root_path}/:username/preferences/second-factor" => "users#preferences", constraints: { username: RouteFormat.username }
  341. delete "#{root_path}/:username/preferences/user_image" => "users#destroy_user_image", constraints: { username: RouteFormat.username }
  342. put "#{root_path}/:username/preferences/avatar/pick" => "users#pick_avatar", constraints: { username: RouteFormat.username }
  343. get "#{root_path}/:username/preferences/card-badge" => "users#card_badge", constraints: { username: RouteFormat.username }
  344. put "#{root_path}/:username/preferences/card-badge" => "users#update_card_badge", constraints: { username: RouteFormat.username }
  345. get "#{root_path}/:username/staff-info" => "users#staff_info", constraints: { username: RouteFormat.username }
  346. get "#{root_path}/:username/summary" => "users#summary", constraints: { username: RouteFormat.username }
  347. get "#{root_path}/:username/invited" => "users#invited", constraints: { username: RouteFormat.username }
  348. get "#{root_path}/:username/invited_count" => "users#invited_count", constraints: { username: RouteFormat.username }
  349. get "#{root_path}/:username/invited/:filter" => "users#invited", constraints: { username: RouteFormat.username }
  350. post "#{root_path}/action/send_activation_email" => "users#send_activation_email"
  351. get "#{root_path}/:username/summary" => "users#show", constraints: { username: RouteFormat.username }
  352. get "#{root_path}/:username/activity/topics.rss" => "list#user_topics_feed", format: :rss, constraints: { username: RouteFormat.username }
  353. get "#{root_path}/:username/activity.rss" => "posts#user_posts_feed", format: :rss, constraints: { username: RouteFormat.username }
  354. get "#{root_path}/:username/activity" => "users#show", constraints: { username: RouteFormat.username }
  355. get "#{root_path}/:username/activity/:filter" => "users#show", constraints: { username: RouteFormat.username }
  356. get "#{root_path}/:username/badges" => "users#badges", constraints: { username: RouteFormat.username }
  357. get "#{root_path}/:username/notifications" => "users#show", constraints: { username: RouteFormat.username }
  358. get "#{root_path}/:username/notifications/:filter" => "users#show", constraints: { username: RouteFormat.username }
  359. get "#{root_path}/:username/activity/pending" => "users#show", constraints: { username: RouteFormat.username }
  360. delete "#{root_path}/:username" => "users#destroy", constraints: { username: RouteFormat.username }
  361. get "#{root_path}/by-external/:external_id" => "users#show", constraints: { external_id: /[^\/]+/ }
  362. get "#{root_path}/:username/flagged-posts" => "users#show", constraints: { username: RouteFormat.username }
  363. get "#{root_path}/:username/deleted-posts" => "users#show", constraints: { username: RouteFormat.username }
  364. get "#{root_path}/:username/topic-tracking-state" => "users#topic_tracking_state", constraints: { username: RouteFormat.username }
  365. end
  366. get "user-badges/:username.json" => "user_badges#username", constraints: { username: RouteFormat.username }, defaults: { format: :json }
  367. get "user-badges/:username" => "user_badges#username", constraints: { username: RouteFormat.username }
  368. post "user_avatar/:username/refresh_gravatar" => "user_avatars#refresh_gravatar", constraints: { username: RouteFormat.username }
  369. get "letter_avatar/:username/:size/:version.png" => "user_avatars#show_letter", format: false, constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username }
  370. get "user_avatar/:hostname/:username/:size/:version.png" => "user_avatars#show", format: false, constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username }
  371. # in most production settings this is bypassed
  372. get "letter_avatar_proxy/:version/letter/:letter/:color/:size.png" => "user_avatars#show_proxy_letter"
  373. get "highlight-js/:hostname/:version.js" => "highlight_js#show", format: false, constraints: { hostname: /[\w\.-]+/ }
  374. get "stylesheets/:name.css.map" => "stylesheets#show_source_map", constraints: { name: /[-a-z0-9_]+/ }
  375. get "stylesheets/:name.css" => "stylesheets#show", constraints: { name: /[-a-z0-9_]+/ }
  376. post "uploads" => "uploads#create"
  377. post "uploads/lookup-urls" => "uploads#lookup_urls"
  378. # used to download original images
  379. get "uploads/:site/:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, sha: /\h{40}/, extension: /[a-z0-9\.]+/i }
  380. # used to download attachments
  381. 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 }
  382. # used to download attachments (old route)
  383. get "uploads/:site/:id/:sha" => "uploads#show", constraints: { site: /\w+/, id: /\d+/, sha: /\h{16}/ }
  384. get "posts" => "posts#latest", id: "latest_posts"
  385. get "private-posts" => "posts#latest", id: "private_posts"
  386. get "posts/by_number/:topic_id/:post_number" => "posts#by_number"
  387. get "posts/:id/reply-history" => "posts#reply_history"
  388. get "posts/:id/reply-ids" => "posts#reply_ids"
  389. get "posts/:username/deleted" => "posts#deleted_posts", constraints: { username: RouteFormat.username }
  390. get "posts/:username/flagged" => "posts#flagged_posts", constraints: { username: RouteFormat.username }
  391. resources :groups, id: RouteFormat.username do
  392. get "posts.rss" => "groups#posts_feed", format: :rss
  393. get "mentions.rss" => "groups#mentions_feed", format: :rss
  394. get 'members'
  395. get 'posts'
  396. get 'mentions'
  397. get 'counts'
  398. get 'mentionable'
  399. get 'messageable'
  400. get 'logs' => 'groups#histories'
  401. collection do
  402. get 'custom/new' => 'groups#new', constraints: AdminConstraint.new
  403. get "search" => "groups#search"
  404. end
  405. member do
  406. %w{
  407. activity
  408. activity/:filter
  409. messages
  410. messages/inbox
  411. messages/archive
  412. manage
  413. manage/profile
  414. manage/members
  415. manage/membership
  416. manage/interaction
  417. manage/logs
  418. }.each do |path|
  419. get path => 'groups#show'
  420. end
  421. put "members" => "groups#add_members"
  422. delete "members" => "groups#remove_member"
  423. post "request_membership" => "groups#request_membership"
  424. post "notifications" => "groups#set_notifications"
  425. end
  426. end
  427. # aliases so old API code works
  428. delete "admin/groups/:id/members" => "groups#remove_member", constraints: AdminConstraint.new
  429. put "admin/groups/:id/members" => "groups#add_members", constraints: AdminConstraint.new
  430. resources :posts do
  431. put "bookmark"
  432. put "wiki"
  433. put "post_type"
  434. put "rebake"
  435. put "unhide"
  436. put "locked"
  437. get "replies"
  438. get "revisions/latest" => "posts#latest_revision"
  439. get "revisions/:revision" => "posts#revisions", constraints: { revision: /\d+/ }
  440. put "revisions/:revision/hide" => "posts#hide_revision", constraints: { revision: /\d+/ }
  441. put "revisions/:revision/show" => "posts#show_revision", constraints: { revision: /\d+/ }
  442. put "revisions/:revision/revert" => "posts#revert", constraints: { revision: /\d+/ }
  443. put "recover"
  444. collection do
  445. delete "destroy_many"
  446. put "merge_posts"
  447. end
  448. end
  449. resources :notifications, except: :show do
  450. collection do
  451. put 'mark-read' => 'notifications#mark_read'
  452. # creating an alias cause the api was extended to mark a single notification
  453. # this allows us to cleanly target it
  454. put 'read' => 'notifications#mark_read'
  455. end
  456. end
  457. match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: [:get, :post]
  458. match "/auth/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post]
  459. resources :clicks do
  460. collection do
  461. get "track"
  462. end
  463. end
  464. get "excerpt" => "excerpt#show"
  465. resources :post_action_users
  466. resources :post_actions do
  467. collection do
  468. get "users"
  469. post "defer_flags"
  470. end
  471. end
  472. resources :user_actions
  473. resources :badges, only: [:index]
  474. get "/badges/:id(/:slug)" => "badges#show"
  475. resources :user_badges, only: [:index, :create, :destroy]
  476. get '/c', to: redirect(relative_url_root + 'categories')
  477. resources :categories, except: :show
  478. post "category/:category_id/move" => "categories#move"
  479. post "categories/reorder" => "categories#reorder"
  480. post "category/:category_id/notifications" => "categories#set_notifications"
  481. put "category/:category_id/slug" => "categories#update_slug"
  482. get "categories_and_latest" => "categories#categories_and_latest"
  483. get "categories_and_top" => "categories#categories_and_top"
  484. get "c/:id/show" => "categories#show"
  485. get "c/:category_slug/find_by_slug" => "categories#find_by_slug"
  486. get "c/:parent_category_slug/:category_slug/find_by_slug" => "categories#find_by_slug"
  487. get "c/:category.rss" => "list#category_feed", format: :rss
  488. get "c/:parent_category/:category.rss" => "list#category_feed", format: :rss
  489. get "c/:category" => "list#category_default", as: "category_default"
  490. get "c/:category/none" => "list#category_none_latest"
  491. get "c/:parent_category/:category/(:id)" => "list#parent_category_category_latest", constraints: { id: /\d+/ }
  492. get "c/:category/l/top" => "list#category_top", as: "category_top"
  493. get "c/:category/none/l/top" => "list#category_none_top", as: "category_none_top"
  494. get "c/:parent_category/:category/l/top" => "list#parent_category_category_top", as: "parent_category_category_top"
  495. get "category_hashtags/check" => "category_hashtags#check"
  496. TopTopic.periods.each do |period|
  497. get "top/#{period}.rss" => "list#top_#{period}_feed", format: :rss
  498. get "top/#{period}" => "list#top_#{period}"
  499. get "c/:category/l/top/#{period}" => "list#category_top_#{period}", as: "category_top_#{period}"
  500. get "c/:category/none/l/top/#{period}" => "list#category_none_top_#{period}", as: "category_none_top_#{period}"
  501. get "c/:parent_category/:category/l/top/#{period}" => "list#parent_category_category_top_#{period}", as: "parent_category_category_top_#{period}"
  502. end
  503. Discourse.anonymous_filters.each do |filter|
  504. get "#{filter}.rss" => "list##{filter}_feed", format: :rss
  505. end
  506. Discourse.filters.each do |filter|
  507. get "#{filter}" => "list##{filter}", constraints: { format: /(json|html)/ }
  508. get "c/:category/l/#{filter}" => "list#category_#{filter}", as: "category_#{filter}"
  509. get "c/:category/none/l/#{filter}" => "list#category_none_#{filter}", as: "category_none_#{filter}"
  510. get "c/:parent_category/:category/l/#{filter}" => "list#parent_category_category_#{filter}", as: "parent_category_category_#{filter}"
  511. end
  512. get "category/*path" => "categories#redirect"
  513. get "top" => "list#top"
  514. get "search/query" => "search#query"
  515. get "search" => "search#show"
  516. post "search/click" => "search#click"
  517. # Topics resource
  518. get "t/:id" => "topics#show"
  519. put "t/:id" => "topics#update"
  520. delete "t/:id" => "topics#destroy"
  521. put "t/:id/archive-message" => "topics#archive_message"
  522. put "t/:id/move-to-inbox" => "topics#move_to_inbox"
  523. put "t/:id/convert-topic/:type" => "topics#convert_topic"
  524. put "t/:id/publish" => "topics#publish"
  525. put "t/:id/shared-draft" => "topics#update_shared_draft"
  526. put "topics/bulk"
  527. put "topics/reset-new" => 'topics#reset_new'
  528. post "topics/timings"
  529. get 'topics/similar_to' => 'similar_topics#index'
  530. resources :similar_topics
  531. get "topics/feature_stats"
  532. scope "/topics", username: RouteFormat.username do
  533. get "created-by/:username" => "list#topics_by", as: "topics_by"
  534. get "private-messages/:username" => "list#private_messages", as: "topics_private_messages"
  535. get "private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent"
  536. get "private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive"
  537. get "private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread"
  538. get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", as: "topics_private_messages_tag", constraints: StaffConstraint.new
  539. get "groups/:group_name" => "list#group_topics", as: "group_topics", group_name: RouteFormat.username
  540. scope "/private-messages-group/:username", group_name: RouteFormat.username do
  541. get ":group_name.json" => "list#private_messages_group", as: "topics_private_messages_group"
  542. get ":group_name/archive.json" => "list#private_messages_group_archive", as: "topics_private_messages_group_archive"
  543. end
  544. end
  545. get 'embed/comments' => 'embed#comments'
  546. get 'embed/count' => 'embed#count'
  547. get 'embed/info' => 'embed#info'
  548. get "new-topic" => "list#latest"
  549. get "new-message" => "list#latest"
  550. # Topic routes
  551. get "t/id_for/:slug" => "topics#id_for_slug"
  552. get "t/:slug/:topic_id/print" => "topics#show", format: :html, print: true, constraints: { topic_id: /\d+/ }
  553. get "t/:slug/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ }
  554. get "t/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ }
  555. get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", constraints: { topic_id: /\d+/ }
  556. get "t/:slug/:topic_id/summary" => "topics#show", defaults: { summary: true }, constraints: { topic_id: /\d+/ }
  557. get "t/:topic_id/summary" => "topics#show", constraints: { topic_id: /\d+/ }
  558. put "t/:slug/:topic_id" => "topics#update", constraints: { topic_id: /\d+/ }
  559. put "t/:slug/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ }
  560. put "t/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ }
  561. put "t/:slug/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ }
  562. put "t/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ }
  563. put "t/:topic_id/clear-pin" => "topics#clear_pin", constraints: { topic_id: /\d+/ }
  564. put "t/:topic_id/re-pin" => "topics#re_pin", constraints: { topic_id: /\d+/ }
  565. put "t/:topic_id/mute" => "topics#mute", constraints: { topic_id: /\d+/ }
  566. put "t/:topic_id/unmute" => "topics#unmute", constraints: { topic_id: /\d+/ }
  567. post "t/:topic_id/timer" => "topics#timer", constraints: { topic_id: /\d+/ }
  568. put "t/:topic_id/make-banner" => "topics#make_banner", constraints: { topic_id: /\d+/ }
  569. put "t/:topic_id/remove-banner" => "topics#remove_banner", constraints: { topic_id: /\d+/ }
  570. put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", constraints: { topic_id: /\d+/ }
  571. put "t/:topic_id/remove-allowed-group" => "topics#remove_allowed_group", constraints: { topic_id: /\d+/ }
  572. put "t/:topic_id/recover" => "topics#recover", constraints: { topic_id: /\d+/ }
  573. get "t/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ }
  574. get "t/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ }
  575. get "t/:slug/:topic_id.rss" => "topics#feed", format: :rss, constraints: { topic_id: /\d+/ }
  576. get "t/:slug/:topic_id" => "topics#show", constraints: { topic_id: /\d+/ }
  577. get "t/:slug/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ }
  578. get "t/:slug/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ }
  579. get "t/:topic_id/posts" => "topics#posts", constraints: { topic_id: /\d+/ }, format: :json
  580. get "t/:topic_id/excerpts" => "topics#excerpts", constraints: { topic_id: /\d+/ }, format: :json
  581. post "t/:topic_id/timings" => "topics#timings", constraints: { topic_id: /\d+/ }
  582. post "t/:topic_id/invite" => "topics#invite", constraints: { topic_id: /\d+/ }
  583. post "t/:topic_id/invite-group" => "topics#invite_group", constraints: { topic_id: /\d+/ }
  584. post "t/:topic_id/move-posts" => "topics#move_posts", constraints: { topic_id: /\d+/ }
  585. post "t/:topic_id/merge-topic" => "topics#merge_topic", constraints: { topic_id: /\d+/ }
  586. post "t/:topic_id/change-owner" => "topics#change_post_owners", constraints: { topic_id: /\d+/ }
  587. put "t/:topic_id/change-timestamp" => "topics#change_timestamps", constraints: { topic_id: /\d+/ }
  588. delete "t/:topic_id/timings" => "topics#destroy_timings", constraints: { topic_id: /\d+/ }
  589. put "t/:topic_id/bookmark" => "topics#bookmark", constraints: { topic_id: /\d+/ }
  590. put "t/:topic_id/remove_bookmarks" => "topics#remove_bookmarks", constraints: { topic_id: /\d+/ }
  591. post "t/:topic_id/notifications" => "topics#set_notifications" , constraints: { topic_id: /\d+/ }
  592. get "p/:post_id(/:user_id)" => "posts#short_link"
  593. get "/posts/:id/cooked" => "posts#cooked"
  594. get "/posts/:id/expand-embed" => "posts#expand_embed"
  595. get "/posts/:id/raw" => "posts#markdown_id"
  596. get "/posts/:id/raw-email" => "posts#raw_email"
  597. get "raw/:topic_id(/:post_number)" => "posts#markdown_num"
  598. resources :queued_posts, constraints: StaffConstraint.new
  599. get 'queued-posts' => 'queued_posts#index'
  600. resources :invites
  601. post "invites/upload_csv" => "invites#upload_csv"
  602. post "invites/rescind-all" => "invites#rescind_all_invites"
  603. post "invites/reinvite" => "invites#resend_invite"
  604. post "invites/reinvite-all" => "invites#resend_all_invites"
  605. post "invites/link" => "invites#create_invite_link"
  606. delete "invites" => "invites#destroy"
  607. put "invites/show/:id" => "invites#perform_accept_invitation", as: 'perform_accept_invite'
  608. resources :export_csv do
  609. collection do
  610. post "export_entity" => "export_csv#export_entity"
  611. end
  612. member do
  613. get "" => "export_csv#show", constraints: { id: /[^\/]+/ }
  614. end
  615. end
  616. get "onebox" => "onebox#show"
  617. get "inline-onebox" => "inline_onebox#show"
  618. get "exception" => "list#latest"
  619. get "message-bus/poll" => "message_bus#poll"
  620. get "draft" => "draft#show"
  621. post "draft" => "draft#update"
  622. delete "draft" => "draft#destroy"
  623. if service_worker_asset = Rails.application.assets_manifest.assets['service-worker.js']
  624. # https://developers.google.com/web/fundamentals/codelabs/debugging-service-workers/
  625. # Normally the browser will wait until a user closes all tabs that contain the
  626. # current site before updating to a new Service Worker.
  627. # Support the old Service Worker path to avoid routing error filling up the
  628. # logs.
  629. get "/service-worker.js" => redirect(relative_url_root + service_worker_asset), format: :js
  630. get service_worker_asset => "static#service_worker_asset", format: :js
  631. elsif Rails.env.development?
  632. get "/service-worker.js" => "static#service_worker_asset", format: :js
  633. end
  634. get "cdn_asset/:site/*path" => "static#cdn_asset", format: false
  635. get "brotli_asset/*path" => "static#brotli_asset", format: false
  636. get "favicon/proxied" => "static#favicon", format: false
  637. get "robots.txt" => "robots_txt#index"
  638. get "robots-builder.json" => "robots_txt#builder"
  639. get "offline.html" => "offline#index"
  640. get "manifest.json" => "metadata#manifest", as: :manifest
  641. get "opensearch" => "metadata#opensearch", format: :xml
  642. scope "/tags" do
  643. get '/' => 'tags#index'
  644. get '/filter/list' => 'tags#index'
  645. get '/filter/search' => 'tags#search'
  646. get '/check' => 'tags#check_hashtag'
  647. get '/personal_messages/:username' => 'tags#personal_messages'
  648. constraints(tag_id: /[^\/]+?/, format: /json|rss/) do
  649. get '/:tag_id.rss' => 'tags#tag_feed'
  650. get '/:tag_id' => 'tags#show', as: 'tag_show'
  651. get '/c/:category/:tag_id' => 'tags#show', as: 'tag_category_show'
  652. get '/c/:parent_category/:category/:tag_id' => 'tags#show', as: 'tag_parent_category_category_show'
  653. get '/intersection/:tag_id/*additional_tag_ids' => 'tags#show', as: 'tag_intersection'
  654. get '/:tag_id/notifications' => 'tags#notifications'
  655. put '/:tag_id/notifications' => 'tags#update_notifications'
  656. put '/:tag_id' => 'tags#update'
  657. delete '/:tag_id' => 'tags#destroy'
  658. Discourse.filters.each do |filter|
  659. get "/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_show_#{filter}"
  660. get "/c/:category/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_show_#{filter}"
  661. get "/c/:parent_category/:category/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_parent_category_category_show_#{filter}"
  662. end
  663. end
  664. end
  665. resources :tag_groups, except: [:new, :edit] do
  666. collection do
  667. get '/filter/search' => 'tag_groups#search'
  668. end
  669. end
  670. Discourse.filters.each do |filter|
  671. root to: "list##{filter}", constraints: HomePageConstraint.new("#{filter}"), as: "list_#{filter}"
  672. end
  673. # special case for categories
  674. root to: "categories#index", constraints: HomePageConstraint.new("categories"), as: "categories_index"
  675. # special case for top
  676. root to: "list#top", constraints: HomePageConstraint.new("top"), as: "top_lists"
  677. root to: 'finish_installation#index', constraints: HomePageConstraint.new("finish_installation"), as: 'installation_redirect'
  678. get "/user-api-key/new" => "user_api_keys#new"
  679. post "/user-api-key" => "user_api_keys#create"
  680. post "/user-api-key/revoke" => "user_api_keys#revoke"
  681. post "/user-api-key/undo-revoke" => "user_api_keys#undo_revoke"
  682. get "/safe-mode" => "safe_mode#index"
  683. post "/safe-mode" => "safe_mode#enter", as: "safe_mode_enter"
  684. get "/themes/assets/:key" => "themes#assets"
  685. get "*url", to: 'permalinks#show', constraints: PermalinkConstraint.new
  686. end