diff --git a/docs/api/api/obs.rng b/docs/api/api/obs.rng index 8e7cec8e8618d384d83dc3580c0641511dfd634b..9abc5bd464489904f345c6c8ab2a3535b43935b2 100644 --- a/docs/api/api/obs.rng +++ b/docs/api/api/obs.rng @@ -149,6 +149,14 @@ </element> </define> + <define ns="" name="allowbuilddep-element"> + <element name="allowbuilddep"> + <attribute name="name"> + <data type="string" /> + </attribute> + </element> + </define> + <define ns="" name="group-element"> <element name="group"> <attribute name="groupid"> diff --git a/docs/api/api/project.rng b/docs/api/api/project.rng index fd02c18dc41d9999d539199fd8a42e53ed229c69..14e901604561ebf5cf256b01ee2755d274593bcd 100644 --- a/docs/api/api/project.rng +++ b/docs/api/api/project.rng @@ -95,6 +95,10 @@ </element> </optional> + <zeroOrMore> + <ref name="allowbuilddep-element"/> + </zeroOrMore> + <zeroOrMore> <ref name="person-element"/> </zeroOrMore> diff --git a/src/api/app/controllers/source_controller.rb b/src/api/app/controllers/source_controller.rb index 2a2150b1987b858274fb472036c7d7c9d8016e64..e26a61520baeea63956b6bbe91925b84aff68c08 100644 --- a/src/api/app/controllers/source_controller.rb +++ b/src/api/app/controllers/source_controller.rb @@ -432,6 +432,13 @@ class SourceController < ApplicationController else # access check prj = Project.get_by_name params[:project] + # since users may now see different versions of the + # project XML depending on their access permissions + # to linked projects, and the cache is global, we must + # invalidate the cache before reconstructing the xml. + if prj.id + Rails.cache.delete("xml_project_#{prj.id}") + end render xml: prj.to_axml end end diff --git a/src/api/app/models/allowbuilddep.rb b/src/api/app/models/allowbuilddep.rb new file mode 100644 index 0000000000000000000000000000000000000000..c774b5ecf84b0cfc83d2029dfb823c5b57bdc624 --- /dev/null +++ b/src/api/app/models/allowbuilddep.rb @@ -0,0 +1,3 @@ +class Allowbuilddep < ActiveRecord::Base + belongs_to :project, foreign_key: :db_project_id, inverse_of: :allowbuilddeps +end diff --git a/src/api/app/models/project.rb b/src/api/app/models/project.rb index bfcb1a145a349ed0fd0b33279ec477b3e8a80ee6..f51a256b77f6caa393c92099ad3fa4bbd9336e2f 100644 --- a/src/api/app/models/project.rb +++ b/src/api/app/models/project.rb @@ -51,6 +51,8 @@ class Project < ActiveRecord::Base end has_many :attribs, :dependent => :destroy + has_many :allowbuilddeps, :dependent => :destroy, foreign_key: :db_project_id + has_many :repositories, :dependent => :destroy, foreign_key: :db_project_id has_many :repository_architectures, -> { order("position") }, through: :repositories has_many :architectures, -> { order("position").distinct }, :through => :repository_architectures @@ -575,6 +577,7 @@ class Project < ActiveRecord::Base #--- update repositories ---# update_repositories(xmlhash, force) #--- end update repositories ---# + update_allowbuilddep_from_xml(xmlhash) end def update_from_xml(xmlhash, force = nil) @@ -584,6 +587,13 @@ class Project < ActiveRecord::Base { error: e.message } end + def update_allowbuilddep_from_xml(xmlhash) + self.allowbuilddeps.destroy_all + xmlhash.elements('allowbuilddep') do |abd| + self.allowbuilddeps.create(name: abd['name']) + end + end + def update_repositories(xmlhash, force) fill_repo_cache @@ -1719,7 +1729,8 @@ class Project < ActiveRecord::Base target_project = Project.get_by_name(target_project_name) # user can access tprj, but backend would refuse to take binaries from there if target_project.class == Project && target_project.disabled_for?('access', nil, nil) - return { error: "The current backend implementation is not using binaries from read access protected projects #{target_project_name}"} + # RBEI modification to ACL logic: upstream returns an { error: "… read access protected …" } here. + logger.info "Project #{project_name} depends on restricted project #{target_project_name}" end end logger.debug "Project #{project_name} repository path checked against #{target_project_name} projects permission" diff --git a/src/api/app/views/models/_project.xml.builder b/src/api/app/views/models/_project.xml.builder index 530c7deb5ef469e19a3e3186c4aedbb7752c4f5e..1d566a7f293b4b0a3706c264f952056e9cedcef9 100644 --- a/src/api/app/views/models/_project.xml.builder +++ b/src/api/app/views/models/_project.xml.builder @@ -20,6 +20,11 @@ xml.project(project_attributes) do my_model.render_relationships(xml) + adbs = my_model.allowbuilddeps.sort { |a, b| b.name <=> a.name } + adbs.each do |adb| + xml.allowbuilddep(name: adb.name) + end + repos = my_model.repositories.not_remote.sort { |a, b| b.name <=> a.name } FlagHelper.flag_types.each do |flag_name| flaglist = my_model.type_flags(flag_name) @@ -62,10 +67,13 @@ xml.project(project_attributes) do repo.path_elements.includes(:link).each do |pe| if pe.link.remote_project_name project_name = pe.link.project.name+":"+pe.link.remote_project_name - else + xml_repository.path(:project => project_name, :repository => pe.link.name) + elsif pe.link.project project_name = pe.link.project.name + xml_repository.path(:project => project_name, :repository => pe.link.name) + else + xml_repository.path(:project => "HIDDEN", :repository => pe.link.name) end - xml_repository.path(:project => project_name, :repository => pe.link.name) end repo.repository_architectures.joins(:architecture).pluck("architectures.name").each do |arch| xml_repository.arch arch diff --git a/src/api/db/migrate/20191011000000_create_allowbuilddeps.rb b/src/api/db/migrate/20191011000000_create_allowbuilddeps.rb new file mode 100644 index 0000000000000000000000000000000000000000..f4de5797495a1b326eb13a54679e85fc61ccb052 --- /dev/null +++ b/src/api/db/migrate/20191011000000_create_allowbuilddeps.rb @@ -0,0 +1,13 @@ +class CreateAllowbuilddeps < ActiveRecord::Migration + def self.up + create_table :allowbuilddeps do |t| + t.integer :db_project_id, :null => false + t.string :name, :null => false + t.index [ :db_project_id, :name ] + end + end + + def self.down + drop_table :allowbuilddeps + end +end diff --git a/src/api/db/structure.sql b/src/api/db/structure.sql index 88a174effeb9c0e682aa277420fbca403c315b7f..7d829d4d35e05ea6780b9272b2ade2e08a306362 100644 --- a/src/api/db/structure.sql +++ b/src/api/db/structure.sql @@ -1,3 +1,11 @@ +CREATE TABLE `allowbuilddeps` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `db_project_id` int(11) NOT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + KEY `index_allowbuilddeps_on_db_project_id_and_name` (`db_project_id`,`name`(191)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + CREATE TABLE `architectures` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 NOT NULL, @@ -1682,6 +1690,8 @@ INSERT INTO schema_migrations (version) VALUES ('20160518105300'); INSERT INTO schema_migrations (version) VALUES ('20160824132643'); +INSERT INTO schema_migrations (version) VALUES ('20191011000000'); + INSERT INTO schema_migrations (version) VALUES ('21'); INSERT INTO schema_migrations (version) VALUES ('22'); diff --git a/src/backend/BSSched/Access.pm b/src/backend/BSSched/Access.pm index d4133b362bfc1eb044d45ff7d16316eb2cd5548c..dc5ffaac3737351c633ac785110b9b47e892de7c 100644 --- a/src/backend/BSSched/Access.pm +++ b/src/backend/BSSched/Access.pm @@ -42,6 +42,19 @@ sub checkaccess { return $access; } +sub checkbuilddepok { + my ($gctx, $projid, $aprojid) = @_; + + my $adata = $gctx->{projpacks}->{$aprojid} || {}; + my $allow = $adata->{allowbuilddep} || []; + + foreach my $a ( grep { ref($_) eq 'HASH' } @$allow ) { + if( $a->{name} eq $projid ) { return 1; } + } + + return 0; +} + # check if every user from oprojid may access projid sub checkroles { my ($gctx, $type, $projid, $packid, $oprojid, $opackid) = @_; @@ -101,6 +114,13 @@ sub checkprpaccess { # ok if aprp is not protected return 1 if checkaccess($gctx, 'access', $aprojid, undef, $arepoid); my ($projid, $repoid) = split('/', $prp, 2); + + ################################################################# + # this is an RBEI modification + # ok if prp has access to aprp (via allowbuilddep in project meta): + return 1 if checkbuilddepok($gctx, $projid, $aprojid); + ################################################################# + # not ok if prp is unprotected return 0 if checkaccess($gctx, 'access', $projid, undef, $repoid); # both prp and aprp are proteced. diff --git a/src/backend/BSXML.pm b/src/backend/BSXML.pm index f9d296b500dced101748366b7a1b64215bd1acde..45ca785cd28fa911adcec8763655da8e7650268c 100644 --- a/src/backend/BSXML.pm +++ b/src/backend/BSXML.pm @@ -115,6 +115,10 @@ our @flags = ( [ 'access' => @disableenable ], ); +our @allowbuilddep = ( + [[ 'allowbuilddep' => 'name' ]], +); + our @roles = ( [[ 'person' => 'userid', @@ -151,6 +155,7 @@ our $proj = [ 'project', ], @roles, + @allowbuilddep, $maintenance, @flags, [ $repo ], @@ -292,6 +297,7 @@ our $projpack = [ [], 'title', 'description', + @allowbuilddep, 'config', 'patternmd5', [[ 'link' => diff --git a/src/backend/bs_srcserver b/src/backend/bs_srcserver index 383d600f5492bb001d0cad1f5c37b3eaef1c7c6e..72a05eca610f90e23771f973a4396602354b803a 100755 --- a/src/backend/bs_srcserver +++ b/src/backend/bs_srcserver @@ -3266,7 +3266,7 @@ sub getprojpack { } next if $repoids && !grep {$repoids->{$_->{'name'}}} @{$proj->{'repository'} || []}; next if $packids && !grep {$packids->{$_}} @packages; - for (qw{title description build publish debuginfo useforbuild remoteurl remoteproject download link sourceaccess privacy access lock}) { + for (qw{title description build publish debuginfo useforbuild remoteurl remoteproject download link sourceaccess privacy access lock allowbuilddep}) { $jinfo->{$_} = $proj->{$_} if exists $proj->{$_}; } if ($proj->{'access'}) {