1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# encoding: utf-8
#--
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
require "gitorious/reservations"
require 'routing_filter/base'
module RoutingFilter
class RepositoryOwnerNamespacing < Base
RESERVED_NAMES = Gitorious::Reservations.reserved_root_names
CONTROLLER_NAMES = Gitorious::Reservations.controller_names + RESERVED_NAMES
NAME_WITH_FORMAT_RE = /[a-z0-9_\-\.]+/i
PREFIXES_TO_CONTROLLER = {
"~" => "users",
"+" => "teams",
"" => "projects",
}
PREFIXES_RE = Regexp.union(*PREFIXES_TO_CONTROLLER.keys)
CONTROLLER_RE = Regexp.union(*PREFIXES_TO_CONTROLLER.invert.keys)
# TODO: There's a special place in hell for this kinda logic; clean up
def around_recognize(path, env, &block)
if !reserved?(path)
if path =~ /^\/(#{PREFIXES_RE})(#{NAME_WITH_FORMAT_RE})(\/.+)?/i
controller = PREFIXES_TO_CONTROLLER[$1]
name = $2
rest = $3
if rest && !reserved_action_name?(name, controller) && !reserved?(rest, controller) && repository_scope?(rest)
# Handle repositories namespaced like ":user_or_team_id/:project_id/:repo_id"
rest, project_or_repoish = rest.sub(/^\//, '').split("/", 2).reverse
if !project_or_repoish.blank? && !rest.blank? && !reserved_action_name?(rest, "repositories") # got something that looks namespaced
if reserved_action_name?(rest, controller) # we're looking for an action on repositories
path.replace "/#{controller}/#{name}/repositories/#{project_or_repoish}/#{rest}".chomp("/")
else # We're in the /user_or_team/projectname/... scope
# We actually wanted another controller under repositories, not a repo:
if CONTROLLER_NAMES.include?(rest.split(".", 2).first.split("/")[0])
path.replace "/#{controller}/#{name}/repositories/#{project_or_repoish}/#{rest}".chomp("/")
else
path.replace "/#{controller}/#{name}/projects/#{project_or_repoish}/repositories/#{rest}".chomp("/")
end
end
else
if project_or_repoish
path.replace "/#{controller}/#{name}/repositories/#{project_or_repoish}/#{rest}".chomp("/")
else
path.replace "/#{controller}/#{name}/repositories/#{rest}".chomp("/")
end
end
else
path.replace "/#{controller}/#{name}#{rest}".chomp("/")
end
end
end
yield
# returning yield(path, env) do |params|
# params
# end
end
def around_generate(*args, &block)
params = args.extract_options!
yield.tap do |result|
result = result.is_a?(Array) ? result.first : result
if result =~ /^\/(#{CONTROLLER_RE})\/(#{NAME_WITH_FORMAT_RE})\/repositories\/(#{NAME_WITH_FORMAT_RE})(.+)?/i && !reserved_action_name?($3, $1)
result.replace "/#{PREFIXES_TO_CONTROLLER.invert[$1]}#{$2}/#{$3}#{$4}"
elsif result =~ /^\/(#{CONTROLLER_RE})\/(#{NAME_WITH_FORMAT_RE})(.+)?/i && !reserved_action_name?($2, $1)
controller, id, repo = [$1, $2, $3]
if repo =~ /\/projects\/(#{NAME_WITH_FORMAT_RE})\/repositories\/(#{NAME_WITH_FORMAT_RE})(.+)?/i
#result.replace "/#{PREFIXES_TO_CONTROLLER.invert[controller]}#{id}#{repo}"
result.replace "/#{PREFIXES_TO_CONTROLLER.invert[controller]}#{id}/#{$1}/#{$2}#{$3}"
else
result.replace "/#{PREFIXES_TO_CONTROLLER.invert[controller]}#{id}#{repo}"
end
end
end
end
private
def reserved?(path, controller = nil)
path_with_ending_slash = path.chomp("/") + "/" # Make sure we always only got one slash
(CONTROLLER_NAMES + reserved_actions_for_controller(controller)).any? {|s|
path_with_ending_slash =~ /^\/#{s}(\..+)?\//
}
end
def reserved_action_name?(name, controller)
reserved_actions_for_controller(controller).include?(name)
end
def reserved_actions_for_controller(controller)
case controller
when "users"
UsersController.action_methods.to_a
when "projects"
ProjectsController.action_methods.to_a
when "groups", "teams"
GroupsController.action_methods.to_a
when "repositories"
RepositoriesController.action_methods.to_a
else
[]
end
end
def repository_scope?(path)
!Gitorious::Reservations.projects_member_actions.include?(path.sub("/", "")) &&
path =~ /^\/(#{NAME_WITH_FORMAT_RE})(.+)?$/i
end
end
end
|