Support deployments of Gitorious outside of the root path
[gitorious:mainline.git] / config / routes.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2012 Gitorious AS
4 #
5 #   This program is free software: you can redistribute it and/or modify
6 #   it under the terms of the GNU Affero General Public License as published by
7 #   the Free Software Foundation, either version 3 of the License, or
8 #   (at your option) any later version.
9 #
10 #   This program is distributed in the hope that it will be useful,
11 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #   GNU Affero General Public License for more details.
14 #
15 #   You should have received a copy of the GNU Affero General Public License
16 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #++
18
19 require (Rails.root + "app/racks/git_http_cloner.rb").realpath
20
21 Gitorious::Application.routes.draw do
22   scope (Rails.application.config.relative_url_root || '/') do
23     ### R0. Site index
24     root :to => "site#index"
25
26     ### R1. Git HTTP cloner Rack app
27     match "/:project_id/:repository_id.git/*slug" => Gitorious::GitHttpCloner
28
29     ### R2. User routes
30     resources :users, :only => [:new, :create] do
31       collection do
32         get  "/reset_password/:token" => "users#reset_password", :as => :reset_password
33         get  "/activate/:activation_code" => "users#activate"
34         post "/forgot_password" => "users#forgot_password_create", :as => :forgot_password_create
35         get :forgot_password
36         get :pending_activation
37         get :openid_build
38         post :openid_create
39         get "/new" => "users#new"
40
41         # Used to be we supported things like /users/~zmalltalker/mainline
42         # No more, ~<user_name> is the canonical user URL namespace
43         get "/*slug" => (redirect do |params, request|
44                           request.fullpath.sub("users/", "~")
45                         end), :slug => /.*/
46       end
47     end
48
49     # `resources :users` can't do the ~<user> ids
50     get "/~:id(.:format)" => "users#show", :as => "user", :id => /[^\/]+/
51     get "/~:id/edit(.:format)" => "users#edit", :as => "edit_user", :id => /[^\/]+/
52     put "/~:id(.:format)" => "users#update", :id => /[^\/]+/
53     delete "/~:id(.:format)" => "users#destroy", :id => /[^\/]+/
54
55     # Additional user actions
56     scope "/~:id", :id => /[^\/]+/, :as => :user do
57       get "/delete_current" => "users#delete_current", :as => :delete_current
58       delete "/avatar" => "users#avatar"
59       get "/watchlist" => "users#watchlist", :as => :watchlist
60       get "/password" => "users#password", :as => :password
61       get "/feed" => "users#feed", :as => :feed
62       put "/update_password" => "users#update_password", :as => :update_password
63     end
64
65     # Nested user resources. This is in a separate scope because the
66     # controllers expect params[:user_id] to contain the user, not
67     # params[:id] as in the scope above
68     scope "/~:user_id", :user_id => /[^\/]+/, :as => :user do
69       resources :keys
70
71       resources :aliases do
72         member do
73           get :confirm
74         end
75       end
76
77       get "/repositories" => "repositories#index"
78       resource :license, :only => [:show, :edit, :update]
79       match "/*slug" => "owner_redirections#show"
80     end
81
82     ### R3. Sessions
83     resource :sessions
84     get "/sessions" => "sessions#create", :as => :open_id_complete
85     get "/login" => "sessions#new", :as => :login
86     get "/logout" => "sessions#destroy", :as => :logout
87
88     ### R4. Groups
89     resources :groups, :only => [:index, :new, :create]
90     # `resource :groups` can't do the +<group> ids
91     get "/+:id(.:format)" => "groups#show", :as => "group", :id => /[^\/]+/
92     get "/+:id/edit(.:format)" => "groups#edit", :as => "edit_group", :id => /[^\/]+/
93     put "/+:id(.:format)" => "groups#update", :id => /[^\/]+/
94     delete "/+:id(.:format)" => "groups#destroy", :id => /[^\/]+/
95
96     # Additional group actions
97     scope "/+:id", :id => /[^\/]+/, :as => :group do
98       delete "avatar" => "groups#avatar"
99     end
100
101     # Nested group resources. This is in a separate scope because the
102     # controllers expect params[:group_id] to contain the group, not
103     # params[:id] as in the scope above
104     scope "/+:group_id", :id => /[^\/]+/, :as => :group do
105       resources :memberships
106       get "/repositories" => "repositories#index"
107       match "/*slug" => "owner_redirections#show"
108     end
109
110     ### R5. Site-wide wiki
111     get "/wiki/:site_id/config" => "site_wiki_pages#repository_config", :as => :site_wiki_git_access_connect
112     get "/wiki/:site_id/writable_by" => "site_wiki_pages#writable_by", :as => :site_wiki_git_writable_by
113
114     resources :site_wiki_pages, :path => "/wiki" do
115       collection do
116         get :git_access
117       end
118
119       member do
120         put :preview
121         get :history
122       end
123     end
124
125     ### R6. Direct merge request access
126     match "/merge_request_landing_page" => "merge_requests#oauth_return", :as => :merge_request_landing_page
127     get "/merge_requests/:id" => "merge_requests#direct_access", :as => :merge_request_direct_access
128
129     ### R7. Site controller, various loose pages
130     get "/activities" => "site#public_timeline", :as => :activity
131     get "/dashboard" => "site#dashboard", :as => :dashboard
132     get "/about" => "site#about", :as => :about
133     get "/about/:action" => "site#index", :as => :about_page
134     get "/contact" => "site#contact", :as => :contact
135
136     ### R8. Administration
137     namespace :admin do
138       resources :users, :only => [:index, :new, :create] do
139         member do
140           put :suspend
141           put :flip_admin_status
142           put :unsuspend
143           put :reset_password
144         end
145       end
146
147       resource :oauth_settings
148
149       resources :repositories, :only => [:index] do
150         member do
151           put :recreate
152         end
153       end
154
155       resources :diagnostics, :only => [:index] do
156         collection { get :summary }
157       end
158
159       resources :project_proposals, :only => [:index, :new, :create]
160       post "/project_proposals/:id/reject" => "project_proposals#reject"
161       post "/project_proposals/:id/approve" => "project_proposals#approve"
162     end
163
164     ### R9. API
165     namespace :api do
166       get ":project_id/:repository_id/log/graph(.:format)" => "graphs#show"
167       get ":project_id/:repository_id/log/graph/*branch(.:format)" => "graphs#show"
168     end
169
170     ### R10. Events
171     resources :events do
172       collection do
173         get :commits
174       end
175     end
176
177     ### R11. Additional logged in user resources
178     resources :messages do
179       collection do
180         get :sent
181         put :bulk_update
182         get :all
183         get :auto_complete_for_message_recipients
184       end
185
186       member do
187         post :reply
188         put :read
189       end
190     end
191
192     resources :favorites, :only => [:index, :create, :update, :destroy]
193
194     ### R12. Search
195     get "/search", :controller => "searches", :action => "show", :as => :search
196
197     ### R13. Auto-completion
198     resources :user_auto_completions, :only => [:index]
199     resources :group_auto_completions, :only => [:index]
200
201     ### R14. Projects
202     resources :projects, :only => [:index, :create]
203     get "/:id/edit(.:format)" => "projects#edit"
204
205     resources :projects, :path => "/" do
206       member do
207         put :preview
208         get :edit_slug
209         put :edit_slug
210         get :clones
211         get :confirm_delete
212       end
213
214       resources :project_memberships, :only => [:index, :new, :create, :destroy]
215
216       resources :pages do
217         collection do
218           get :git_access
219         end
220
221         member do
222           put :preview
223           get :history
224         end
225       end
226
227       ### R14.2. Repositories
228
229       # Listing repositories and creating new ones happens over
230       # /<project>/repositories/, e.g:
231       #   /gitorious/repositories/new
232       resources :repositories, :only => [:index, :new, :create]
233
234       # Browsing, editing and destroying existing repositories happens over
235       # /<project>/<repository_name>/, e.g.:
236       #   /gitorious/mainline
237       #   /gitorious/mainline/edit
238       resources(:repositories, {
239                   :path => "/",
240                   :only => [:show, :edit, :update, :destroy]
241                 }) do
242         member do
243           post :create_clone
244           get :clone
245           get :search_clones
246           get :committers
247           get :confirm_delete
248           get :writable_by
249           get "/config" => "repositories#repository_config"
250         end
251
252         resources :comments
253
254         get "/comments/commit/:sha" => "comments#commit", :as => :commit_comment
255         match "/comments/preview" => "comments#preview", :as => :comments_preview, :via => [:get, :post]
256
257         resources :merge_requests do
258           collection do
259             post :create
260             post :commit_list
261             post :target_branches
262           end
263
264           member do
265             get :commit_status
266             get :version
267             get :terms_accepted
268           end
269
270           resources :comments do
271             collection do
272               post :preview
273             end
274           end
275
276           resources :merge_request_versions do
277             resources :comments do
278               collection do
279                 post :preview
280               end
281             end
282           end
283         end
284
285         resources :repository_memberships, :only => [:index, :new, :create, :destroy]
286         resources :committerships
287
288         match "/commits/*id/feed(.:format)" => "commits#feed", :as => :formatted_commits_feed
289         match "/commits" => "commits#index", :as => :commits
290         match "/commits/*branch" => "commits#index", :as => :commits_in_ref
291
292         match "/commit/:id/comments" => "commit_comments#index", :as => :commit_comments, :id => /[^\/]+/
293         match "/commit/:id/diffs" => "commit_diffs#index", :as => :commit_diffs, :id => /[^\/]+/
294         match "/commit/:from_id/diffs/:id" => "commit_diffs#compare", :as => :commit_compare
295         match "/commit/:format/:id" => "commits#show", :as => :commit, :id => /.*/
296         match "/commit/:id" => "commits#show", :as => :commit, :id => /.*/
297
298         match "/graph" => "graphs#index", :as => :graph
299         match "/graph/*branch" => "graphs#index", :as => :graph_in_ref, :branch => /.*/
300
301         match "/trees/" => "trees#index", :as => :trees
302         match "/trees/*branch_and_path" => "trees#show", :as => :tree
303         match "/trees/*branch_and_path.:format" => "trees#show", :as => :formatted_tree
304
305         # These URLs were introduced as a work-around for a Rails bug that
306         # prevented URLs like /archive/:branch.:format. Now we can use the
307         # "real" URLs, redirect these temps to the proper ones.
308         get "/archive-tarball/*branch" => (redirect do |params, request|
309           prefix = request.fullpath.split("/archive-tarball").first
310           "#{prefix}/archive/#{params[:branch]}.tar.gz"
311         end)
312
313         match "/archive/*branch.tar.gz" => "trees#archive", :as => :archive_tar
314         match "/archive/*branch.:archive_format" => "trees#archive", :as => :archive
315
316         match "/blobs/raw/*branch_and_path" => "blobs#raw", :as => :raw_blob
317         match "/blobs/history/*branch_and_path" => "blobs#history", :as => :blob_history
318         match "/blobs/blame/*branch_and_path" => "blobs#blame", :as => :blame
319         match "/blobs/*branch_and_path" => "blobs#show", :as => :blob, :branch_and_path => /.*/
320       end
321     end
322   end
323 end