Skip to content

Commit

Permalink
[api][backend] store attributes to the backend for versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianschroeter committed Jul 4, 2012
1 parent 4283ba0 commit b88cea0
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 56 deletions.
69 changes: 37 additions & 32 deletions src/api/app/controllers/source_controller.rb
Expand Up @@ -498,7 +498,7 @@ def attribute_meta
binary=params[:binary] if params[:binary]
# valid post commands
raise IllegalRequestError.new "invalid_project_name" unless valid_project_name?(params[:project])
if params[:package]
if params[:package] and params[:package] != "_project"
@attribute_container = DbPackage.get_by_project_and_name(params[:project], params[:package], false)
else
# project
Expand Down Expand Up @@ -549,7 +549,13 @@ def attribute_meta
# init
# checks
# exec
render :text => @attribute_container.render_attribute_axml(params), :content_type => 'text/xml'
if params[:rev]
path = "/source/#{URI.escape(params[:project])}/#{URI.escape(params[:package]||'_project')}/_attribute?meta=1&rev=#{CGI.escape(params[:rev])}"
answer = Suse::Backend.get(path)
render :text => answer.body.to_s, :content_type => 'text/xml'
else
render :text => @attribute_container.render_attribute_axml(params), :content_type => 'text/xml'
end
return

# /request.get?
Expand Down Expand Up @@ -583,8 +589,7 @@ def attribute_meta

# exec
ac.destroy
# FIXME: define how to write it to backend
# @attribute_container.store
@attribute_container.write_attributes(params[:comment])
render_ok

# /request.delete?
Expand All @@ -607,37 +612,38 @@ def attribute_meta
end

# checks
if params[:attribute]
unless @http_user.can_create_attribute_in? @attribute_container, :namespace => name_parts[0], :name => name_parts[1]
render_error :status => 403, :errorcode => "change_attribute_no_permission",
:message => "user #{user.login} has no permission to change attribute"
return
end
else
req.each_attribute do |attr|
begin
can_create = @http_user.can_create_attribute_in? @attribute_container, :namespace => attr.namespace, :name => attr.name
rescue ActiveRecord::RecordNotFound => e
render_error :status => 404, :errorcode => "not_found",
:message => e.message
return
rescue ArgumentError => e
render_error :status => 400, :errorcode => "change_attribute_attribute_error",
:message => e.message
return
end
unless can_create
render_error :status => 403, :errorcode => "change_attribute_no_permission",
:message => "user #{user.login} has no permission to change attribute"
return
end
if params[:attribute]
unless @http_user.can_create_attribute_in? @attribute_container, :namespace => name_parts[0], :name => name_parts[1]
render_error :status => 403, :errorcode => "change_attribute_no_permission",
:message => "user #{user.login} has no permission to change attribute"
return
end
end
else
req.each_attribute do |attr|
begin
can_create = @http_user.can_create_attribute_in? @attribute_container, :namespace => attr.namespace, :name => attr.name
rescue ActiveRecord::RecordNotFound => e
render_error :status => 404, :errorcode => "not_found",
:message => e.message
return
rescue ArgumentError => e
render_error :status => 400, :errorcode => "change_attribute_attribute_error",
:message => e.message
return
end
unless can_create
render_error :status => 403, :errorcode => "change_attribute_no_permission",
:message => "user #{user.login} has no permission to change attribute"
return
end
end
end

# exec
changed = false
req.each_attribute do |attr|
begin
@attribute_container.store_attribute_axml(attr, binary)
changed = true if @attribute_container.store_attribute_axml(attr, binary)
rescue DbProject::SaveError => e
render_error :status => 403, :errorcode => "save_error", :message => e.message
return
Expand All @@ -646,8 +652,7 @@ def attribute_meta
return
end
end
# FIXME: define how to write it to backend
# @attribute_container.store
@attribute_container.write_attributes(params[:comment]) if changed
render_ok

# /request.post?
Expand Down
5 changes: 3 additions & 2 deletions src/api/app/models/attrib.rb
Expand Up @@ -20,7 +20,6 @@ def cachekey

def update_from_xml(node)
update_values = false

update_values = true unless node.each_value.length == self.values.count

node.each_value.each_with_index do |val, i|
Expand All @@ -37,9 +36,11 @@ def update_from_xml(node)
self.values << AttribValue.new(:value => val.text, :position => position)
position += 1
end

self.save!
end

self.save
return update_values
end

end
24 changes: 17 additions & 7 deletions src/api/app/models/db_package.rb
Expand Up @@ -615,17 +615,27 @@ def store_attribute_axml( attrib, binary=nil )
end
end
# update or create attribute entry
changed = false
a = find_attribute(attrib.namespace, attrib.name, binary)
if a
a.update_from_xml(attrib)
else
if a.nil?
# create the new attribute entry
if binary
self.attribs.new(:attrib_type => atype, :binary => binary).update_from_xml(attrib)
a = self.attribs.create(:attrib_type => atype, :binary => binary)
else
self.attribs.new(:attrib_type => atype).update_from_xml(attrib)
a = self.attribs.create(:attrib_type => atype)
end
changed = true
end
# write values
changed = true if a.update_from_xml(attrib)
return changed
end

def write_attributes(comment=nil)
login = User.current.login
path = "/source/#{URI.escape(self.db_project.name)}/#{URI.escape(self.name)}/_attribute?meta=1&user=#{CGI.escape(login)}"
path += "&comment=#{CGI.escape(opt[:comment])}" if comment
Suse::Backend.put_source( path, render_attribute_axml )
end

def store(opt={})
Expand Down Expand Up @@ -733,7 +743,7 @@ def to_axml(view = nil)
end
end

def render_issues_axml(params)
def render_issues_axml(params={})
builder = Nokogiri::XML::Builder.new

filter_changes = states = nil
Expand Down Expand Up @@ -763,7 +773,7 @@ def render_issues_axml(params)
Nokogiri::XML::Node::SaveOptions::FORMAT
end

def render_attribute_axml(params)
def render_attribute_axml(params={})
builder = Nokogiri::XML::Builder.new

builder.attributes() do |a|
Expand Down
27 changes: 19 additions & 8 deletions src/api/app/models/db_project.rb
Expand Up @@ -708,7 +708,6 @@ def store(opt={})
Suse::Backend.put_source( path, to_axml )
end

# FIXME: store attributes also to backend
end

def store_attribute_axml( attrib, binary=nil )
Expand Down Expand Up @@ -744,13 +743,25 @@ def store_attribute_axml( attrib, binary=nil )
end
end
end

# update or create attribute entry
if a = find_attribute(attrib.namespace, attrib.name)
a.update_from_xml(attrib)
else
changed = false
a = find_attribute(attrib.namespace, attrib.name)
if a.nil?
# create the new attribute entry
self.attribs.new(:attrib_type => atype).update_from_xml(attrib)
a = self.attribs.create(:attrib_type => atype)
changed = true
end
# write values
changed = true if a.update_from_xml(attrib)
return changed
end

def write_attributes(comment=nil)
login = User.current.login
path = "/source/#{URI.escape(self.name)}/_project/_attribute?meta=1&user=#{CGI.escape(login)}"
path += "&comment=#{CGI.escape(opt[:comment])}" if comment
Suse::Backend.put_source( path, render_attribute_axml )
end

def find_attribute( namespace, name, binary=nil )
Expand All @@ -771,7 +782,7 @@ def find_attribute( namespace, name, binary=nil )
return a
end

def render_issues_axml(params)
def render_issues_axml(params={})
builder = Nokogiri::XML::Builder.new

filter_changes = states = nil
Expand Down Expand Up @@ -802,10 +813,10 @@ def render_issues_axml(params)
Nokogiri::XML::Node::SaveOptions::FORMAT
end

def render_attribute_axml(params)
def render_attribute_axml(params={})
builder = Nokogiri::XML::Builder.new

done={};
done={}
builder.attributes() do |a|
attribs.each do |attr|
next if params[:name] and not attr.attrib_type.name == params[:name]
Expand Down
43 changes: 40 additions & 3 deletions src/api/test/functional/attributes_test.rb
Expand Up @@ -174,7 +174,6 @@ def test_invalid_get
end

def test_create_attributes_project
reset_auth
prepare_request_with_user "tom", "thunder"

data = "<attributes><attribute namespace='OBS' name='Playground'/></attributes>"
Expand Down Expand Up @@ -236,6 +235,18 @@ def test_create_attributes_project
get "/source/home:tom/_attribute/OBS:Maintained"
assert_response :success

# check history
get "/source/home:tom/_project?meta=1"
assert_response :success
assert_xml_tag :tag => "entry", :attributes => { :name => "_attribute" }
get "/source/home:tom/_project/_history?meta=1"
assert_response :success
assert_xml_tag( :tag => "revisionlist" )
node = ActiveXML::XMLNode.new(@response.body)
revision = node.each_revision.last
assert_equal revision.user.text, "tom"
srcmd5 = revision.srcmd5.text

# delete
prepare_request_with_user "tom", "thunder"
post "/source/home:tom/_attribute", data
Expand All @@ -245,6 +256,16 @@ def test_create_attributes_project
delete "/source/home:tom/_attribute/OBS:Maintained"
assert_response 404

# get old revision
# both ways need to work, first one for backward compatibility
get "/source/home:tom/_attribute?rev=#{srcmd5}"
assert_response :success
assert_xml_tag( :tag => "attribute", :attributes => { :namespace => "OBS", :name => "Maintained" } )
get "/source/home:tom/_project/_attribute?meta=1&rev=#{srcmd5}"
assert_response :success
assert_xml_tag( :tag => "attribute", :attributes => { :namespace => "OBS", :name => "Maintained" } )

# get current
get "/source/home:tom/_attribute/OBS:Maintained"
assert_response :success
node = ActiveXML::XMLNode.new(@response.body)
Expand Down Expand Up @@ -305,7 +326,6 @@ def test_create_attributes_package
assert_response 404

# no permission check
reset_auth
prepare_request_with_user "Iggy", "asdfasdf"
post "/source/kde4/kdelibs/_attribute", data
assert_response 403
Expand All @@ -330,6 +350,18 @@ def test_create_attributes_package
assert_response 400
assert_xml_tag :tag => "status", :attributes => { :code => "invalid_attribute" }

# check history
get "/source/kde4/kdelibs?meta=1"
assert_response :success
assert_xml_tag :tag => "entry", :attributes => { :name => "_attribute" }
get "/source/kde4/kdelibs/_history?meta=1"
assert_response :success
assert_xml_tag( :tag => "revisionlist" )
node = ActiveXML::XMLNode.new(@response.body)
revision = node.each_revision.last
assert_equal revision.user.text, "fred"
srcmd5 = revision.srcmd5.text

# delete
reset_auth
prepare_request_with_user "fred", "geröllheimer"
Expand All @@ -347,10 +379,15 @@ def test_create_attributes_package
assert_response :success
node = ActiveXML::XMLNode.new(@response.body)
assert_equal node.has_element?(:attribute), false

# get old revision
get "/source/kde4/kdelibs/_attribute?meta=1&rev=#{srcmd5}"
assert_response :success
assert_xml_tag( :tag => "attribute", :attributes => { :namespace => "OBS", :name => "Maintained" } )
assert_xml_tag( :tag => "attribute", :attributes => { :namespace => "OBS", :name => "Maintained", :binary => "kdelibs-devel" } )
end

# FIXME:
# * attribute search operations missing, but already partly tested via source mbranch
# * value based test are missing

end
Expand Down
16 changes: 16 additions & 0 deletions src/backend/BSVerify.pm
Expand Up @@ -414,4 +414,20 @@ our $verifyers = {
'resultview' => \&verify_resultview,
};

sub verify_attribute {
my $attribute = $_;
die("No namespace defined\n") unless $attribute->{'namespace'};
die("No name defined\n") unless $attribute->{'name'};
for my $value (@{$attribute->{'value'} || []}) {
verify_simple($value);
}
}

sub verify_attributes {
my $attributes = $_;
for my $attribute (@{$attributes || []}) {
verify_attribute($attribute);
}
}

1;
15 changes: 15 additions & 0 deletions src/backend/BSXML.pm
Expand Up @@ -1445,4 +1445,19 @@ our $appdata = [
[ $appdataitem ]
];

our $attribute = [
'attribute' =>
'namespace',
'name',
'binary',
[[ 'value' =>
'_content',
]],
];

our $attributes = [
'attributes' =>
[ $attribute ],
];

1;

0 comments on commit b88cea0

Please sign in to comment.