зеркало из https://github.com/mozilla/labs-vcap.git
Add service plan acls
Change-Id: Ibdcb2779d1e9008459f880b3868f7c918578692c
This commit is contained in:
Родитель
d0623ea983
Коммит
844c756387
|
@ -132,7 +132,7 @@ GEM
|
|||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.26)
|
||||
uuidtools (2.1.2)
|
||||
vcap_common (1.0.8)
|
||||
vcap_common (1.0.10)
|
||||
eventmachine (~> 0.12.11.cloudfoundry.3)
|
||||
nats (~> 0.4.22.beta.8)
|
||||
posix-spawn (~> 0.3.6)
|
||||
|
|
|
@ -37,7 +37,7 @@ class DefaultController < ApplicationController
|
|||
ret[svc_type] ||= {}
|
||||
ret[svc_type][svc.name] ||= {}
|
||||
ret[svc_type][svc.name][svc.version] ||= {}
|
||||
ret[svc_type][svc.name][svc.version] = svc.as_legacy
|
||||
ret[svc_type][svc.name][svc.version] = svc.as_legacy(user)
|
||||
end
|
||||
|
||||
render :json => ret
|
||||
|
|
|
@ -54,7 +54,7 @@ class LegacyServicesController < ApplicationController
|
|||
# Legacy api fell back to matching by vendor if no version matched
|
||||
svc ||= ::Service.find_by_name(req.vendor)
|
||||
|
||||
raise CloudError.new(CloudError::SERVICE_NOT_FOUND) unless svc && svc.visible_to_user?(user)
|
||||
raise CloudError.new(CloudError::SERVICE_NOT_FOUND) unless svc && svc.visible_to_user?(user, req.tier)
|
||||
|
||||
plan_option = nil
|
||||
if req.options && req.options['plan_option']
|
||||
|
|
|
@ -157,7 +157,7 @@ class ServicesController < ApplicationController
|
|||
req = VCAP::Services::Api::CloudControllerProvisionRequest.decode(request_body)
|
||||
|
||||
svc = Service.find_by_label(req.label)
|
||||
raise CloudError.new(CloudError::SERVICE_NOT_FOUND) unless svc && svc.visible_to_user?(user)
|
||||
raise CloudError.new(CloudError::SERVICE_NOT_FOUND) unless svc && svc.visible_to_user?(user, req.plan)
|
||||
|
||||
cfg = ServiceConfig.provision(svc, user, req.name, req.plan, req.plan_option)
|
||||
|
||||
|
|
|
@ -31,33 +31,73 @@ class Service < ActiveRecord::Base
|
|||
# Predicate function that returns true if the service is visible to the supplied
|
||||
# user. False otherwise.
|
||||
#
|
||||
# NB: This is currently a stub. When we implement scoped services it will be filled in.
|
||||
def visible_to_user?(user)
|
||||
(!self.acls || user_in_userlist?(user) || user_match_wildcards?(user))
|
||||
# There are two parts of acls. One is service acls applied to service as a whole
|
||||
# One is plan acls applied to specific service plan.
|
||||
#
|
||||
# A example of acls structure:
|
||||
# acls:
|
||||
# users: #service acls
|
||||
# - foo@bar.com
|
||||
# - foo1@bar.com
|
||||
# wildcards: #service acls
|
||||
# - *@foo.com
|
||||
# - *@foo1.com
|
||||
# plans:
|
||||
# plan_a: #plan acls
|
||||
# users:
|
||||
# - foo2@foo.com
|
||||
# wildcards:
|
||||
# - *@foo1.com
|
||||
#
|
||||
# The following chart shows service visibility:
|
||||
#
|
||||
# P_ACLs\S_ACLs | Empty | HasACLs |
|
||||
# Empty | True | S_ACL(user) |
|
||||
# HasACLs | P_ACL(user) | S_ACL(user) && P_ACL(user) |
|
||||
def visible_to_user?(user, plan=nil)
|
||||
return false if !plans || !user.email
|
||||
return true unless acls
|
||||
|
||||
if !plan
|
||||
plans.each do |p|
|
||||
return true if visible_to_user?(user, p)
|
||||
end
|
||||
return false
|
||||
else
|
||||
# for certain plan, user should match service acls and plan acls
|
||||
p_acls = acls["plans"] && acls["plans"][plan]
|
||||
validate_by_acls?(user, acls) && validate_by_acls?(user, p_acls)
|
||||
end
|
||||
end
|
||||
|
||||
# Return true if acls is empty or user matches user list or wildcards
|
||||
# false otherwise.
|
||||
def validate_by_acls?(user, acl)
|
||||
!acl ||
|
||||
(!acl["users"] && !acl["wildcards"]) ||
|
||||
user_in_userlist?(user, acl["users"]) ||
|
||||
user_match_wildcards?(user, acl["wildcards"])
|
||||
end
|
||||
|
||||
# Returns true if the user's email is contained in the set of user emails
|
||||
def user_in_userlist?(user)
|
||||
return false if (!self.acls || self.acls['users'].empty? || !user.email)
|
||||
return true if self.acls['users'].empty?
|
||||
Set.new(self.acls['users']).include?(user.email)
|
||||
# false otherwise
|
||||
def user_in_userlist?(user, userlist)
|
||||
userlist && userlist.include?(user.email)
|
||||
end
|
||||
|
||||
# Returns true if user matches any of the wildcards, false otherwise.
|
||||
def user_match_wildcards?(user)
|
||||
return false if (!self.acls || self.acls['wildcards'].empty? || !user.email)
|
||||
for wc in self.acls['wildcards']
|
||||
parts = wc.split('*')
|
||||
re_str = parts.map{|p| Regexp.escape(p)}.join('.*')
|
||||
if Regexp.new("^#{re_str}$").match(user.email)
|
||||
return true
|
||||
end
|
||||
end
|
||||
# Returns true if user matches any of the wildcards
|
||||
# false otherwise.
|
||||
def user_match_wildcards?(user, wildcards)
|
||||
wildcards.each do |wc|
|
||||
re_str = Regexp.escape(wc).gsub('\*', '.*?')
|
||||
return true if user.email =~ /^#{re_str}$/
|
||||
end if wildcards
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
# Returns the service represented as a legacy hash
|
||||
def as_legacy
|
||||
def as_legacy(user)
|
||||
# Synthesize tier info
|
||||
tiers = {}
|
||||
|
||||
|
@ -68,6 +108,7 @@ class Service < ActiveRecord::Base
|
|||
end
|
||||
|
||||
self.plans.each do |p|
|
||||
next unless visible_to_user?(user, p)
|
||||
tiers[p] = {
|
||||
:options => {},
|
||||
:order => sort_orders[p], # XXX - Sort order. Synthesized for now (alphabetical), may want to add support for this to svcs api.
|
||||
|
|
|
@ -100,8 +100,8 @@ describe ServicesController do
|
|||
|
||||
it 'should update existing offerings' do
|
||||
acls = {
|
||||
'users' => ['foo@bar.com'],
|
||||
'wildcards' => ['*@foo.com'],
|
||||
'plans' => {'free' => {'users' => ['a@b.com']}}
|
||||
}
|
||||
svc = Service.create(
|
||||
:label => 'foo-bar',
|
||||
|
@ -129,8 +129,8 @@ describe ServicesController do
|
|||
|
||||
it 'should support reverting existing offerings to nil' do
|
||||
acls = {
|
||||
'users' => ['foo@bar.com'],
|
||||
'wildcards' => ['*@foo.com'],
|
||||
'plans' => {'free' => {'users' => ['aaa@bbb.com']}}
|
||||
}
|
||||
svc = Service.create(
|
||||
:label => 'foo-bar',
|
||||
|
@ -384,6 +384,7 @@ describe ServicesController do
|
|||
svc.label = "foo-bar"
|
||||
svc.url = "http://localhost:56789"
|
||||
svc.token = 'foobar'
|
||||
svc.plans = ['free', 'nonfree']
|
||||
svc.save
|
||||
svc.should be_valid
|
||||
@svc = svc
|
||||
|
|
|
@ -74,8 +74,13 @@ describe Service do
|
|||
@user_b.set_and_encrypt_password('foo')
|
||||
@user_b.should be_valid
|
||||
|
||||
@user_c = User.new(:email => 'c@foo.com')
|
||||
@user_c.set_and_encrypt_password('foo')
|
||||
@user_c.should be_valid
|
||||
|
||||
@svc = make_service(
|
||||
:url => 'http://www.foo.com',
|
||||
:plans => ['plan_a', 'plan_b', 'plan_c'],
|
||||
:label => 'foo-bar',
|
||||
:token => 'foobar'
|
||||
)
|
||||
|
@ -83,6 +88,7 @@ describe Service do
|
|||
|
||||
@user_acl_svc = make_service(
|
||||
:url => 'http://www.foo.com',
|
||||
:plans => ['plan_a', 'plan_b', 'plan_c'],
|
||||
:label => 'foo-bar1',
|
||||
:token => 'foobar',
|
||||
:acls => {'users' => ['a@bar.com'], 'wildcards' => []}
|
||||
|
@ -91,14 +97,43 @@ describe Service do
|
|||
|
||||
@wc_acl_svc = make_service(
|
||||
:url => 'http://www.foo.com',
|
||||
:plans => ['plan_a', 'plan_b', 'plan_c'],
|
||||
:label => 'foo-bar2',
|
||||
:token => 'foobar',
|
||||
:acls => {'users' => [], 'wildcards' => ['*@bar.com']}
|
||||
)
|
||||
@wc_acl_svc.should be_valid
|
||||
|
||||
@p_acl_svc = make_service(
|
||||
:url => 'http://www.foo.com',
|
||||
:plans => ['plan_a', 'plan_b', 'plan_c'],
|
||||
:label => 'foo-bar3',
|
||||
:token => 'foobar',
|
||||
:acls => {
|
||||
'plans' => {
|
||||
'plan_a' => {'wildcards' => ['*@bar.com']}
|
||||
}
|
||||
}
|
||||
)
|
||||
@p_acl_svc.should be_valid
|
||||
|
||||
@combo_acl_svc = make_service(
|
||||
:url => 'http://www.foo.com',
|
||||
:plans => ['plan_a', 'plan_b', 'plan_c'],
|
||||
:label => 'foo-bar4',
|
||||
:token => 'foobar',
|
||||
:acls => {
|
||||
'wildcards' => ['*@bar.com'],
|
||||
'plans' => {
|
||||
'plan_a' => {'users' => ['a@bar.com']}
|
||||
}
|
||||
}
|
||||
)
|
||||
@combo_acl_svc.should be_valid
|
||||
end
|
||||
|
||||
it "should return true for services with no acls" do
|
||||
@svc.visible_to_user?(@user_a, 'plan_a').should be_true
|
||||
@svc.visible_to_user?(@user_a).should be_true
|
||||
end
|
||||
|
||||
|
@ -110,6 +145,27 @@ describe Service do
|
|||
it "should correctly validate users in the wildcard acl" do
|
||||
@wc_acl_svc.visible_to_user?(@user_a).should be_true
|
||||
@wc_acl_svc.visible_to_user?(@user_b).should be_true
|
||||
@wc_acl_svc.visible_to_user?(@user_c).should be_false
|
||||
end
|
||||
|
||||
it "should correctly validate user in the plan acls" do
|
||||
@p_acl_svc.visible_to_user?(@user_a).should be_true # can see plan_a, plan_b, plan_c
|
||||
@p_acl_svc.visible_to_user?(@user_b).should be_true # can see plan_a, plan_b, plan_c
|
||||
@p_acl_svc.visible_to_user?(@user_c).should be_true # can see plan_b, plan_c
|
||||
|
||||
@p_acl_svc.visible_to_user?(@user_a, "plan_a").should be_true
|
||||
@p_acl_svc.visible_to_user?(@user_b, "plan_a").should be_true
|
||||
@p_acl_svc.visible_to_user?(@user_c, "plan_a").should be_false
|
||||
end
|
||||
|
||||
it "should correctly validate user in the service acls and the plan acls" do
|
||||
@combo_acl_svc.visible_to_user?(@user_a).should be_true # can see plan_a, plan_b, plan_c
|
||||
@combo_acl_svc.visible_to_user?(@user_b).should be_true # can see plan_b, plan_c
|
||||
@combo_acl_svc.visible_to_user?(@user_c).should be_false # can not see service
|
||||
|
||||
@combo_acl_svc.visible_to_user?(@user_a, "plan_a").should be_true
|
||||
@combo_acl_svc.visible_to_user?(@user_b, "plan_a").should be_false
|
||||
@combo_acl_svc.visible_to_user?(@user_c, "plan_a").should be_false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -26,14 +26,14 @@ module VCAP
|
|||
optional :plans, [String]
|
||||
optional :plan_options
|
||||
optional :binding_options
|
||||
optional :acls, {'users' => [String], 'wildcards' => [String]}
|
||||
optional :acls
|
||||
optional :active
|
||||
optional :timeout, Integer
|
||||
end
|
||||
|
||||
class BrokeredServiceOfferingRequest < JsonMessage
|
||||
required :label, SERVICE_LABEL_REGEX
|
||||
required :options, [{"name" => String, "acls" => {"users" => [String], "wildcards" => [String] } , "credentials" => Hash}]
|
||||
required :options, [{"name" => String, "credentials" => Hash}]
|
||||
optional :description, String
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
spec = Gem::Specification.new do |s|
|
||||
s.name = 'vcap_common'
|
||||
s.version = '1.0.9'
|
||||
s.version = '1.0.10'
|
||||
s.date = '2011-02-09'
|
||||
s.summary = 'vcap common'
|
||||
s.homepage = "http://github.com/vmware-ac/core"
|
||||
|
|
Загрузка…
Ссылка в новой задаче