diff --git a/ReleaseNotes-2.7.1 b/ReleaseNotes-2.7.1 new file mode 100644 index 0000000000000000000000000000000000000000..bceb25e96d11d6fe0e8017f26d6481bb9879cd08 --- /dev/null +++ b/ReleaseNotes-2.7.1 @@ -0,0 +1,32 @@ +# +# openSUSE Build Service 2.7.1 +# + +Updaters from OBS 2.7.0 release can just ugrade the packages +and restart all services. Updaters from former releases should +read the README.UPDATERS file. + +This is in first place a bugfix release focusing on security issues + +Feature backports: +================== + +* none + +Changes: +======== + +* none + +Bugfixes: +========= + +* [webui][api] Update rails to version 4.2.7.1 to fix CVE-2016-6316 and CVE-2016-6317 +* [webui] Users in not 'confirmed' state were allowed to login + +* [api] Users in not 'confirmed' state were allowed to run services via former created token + +* [backend] Fixing project copy which includes binaries +* [backend] worker supports jobs from OBS 2.8 scheduler +* [backend] support publishing of .vdi (VirtualBox image) files + diff --git a/ReleaseNotes-2.7.2 b/ReleaseNotes-2.7.2 new file mode 100644 index 0000000000000000000000000000000000000000..1ca604c9731e8d978a921da64059356be62b82d0 --- /dev/null +++ b/ReleaseNotes-2.7.2 @@ -0,0 +1,26 @@ +# +# openSUSE Build Service 2.7.2 +# + +Updaters from OBS 2.7.0 release can just ugrade the packages +and restart all services. Updaters from former releases should +read the README.UPDATERS file. + +This is in first place a bugfix release focusing on security issues + +Feature backports: +================== + +* none + +Changes: +======== + +* none + +Bugfixes: +========= + +* [webui][api] Sets bs_request_counter correctly + +* [backend] bs_publish: unpublished hook added diff --git a/ReleaseNotes-2.7.3 b/ReleaseNotes-2.7.3 new file mode 100644 index 0000000000000000000000000000000000000000..9aa2a6e7404d80cf87ce22b01bf42d39b278c056 --- /dev/null +++ b/ReleaseNotes-2.7.3 @@ -0,0 +1,28 @@ +# +# openSUSE Build Service 2.7.3 +# + +Updaters from OBS 2.7.0 release can just ugrade the packages +and restart all services. Updaters from former releases should +read the README.UPDATERS file. + +This is in first place a bugfix release focusing on security issues + +Feature backports: +================== + +* none + +Changes: +======== + +* Compability with OBS 2.8 remote instances + +Bugfixes: +========= + +* [api] Project meta data was corrupted after undelete +* [api] Raising access and sourceaccess permissions as admin is working again +* [backend] Download on demand sync fixes +* [webui] Fixed revert to a specified source revision + diff --git a/ReleaseNotes-2.7.4 b/ReleaseNotes-2.7.4 new file mode 100644 index 0000000000000000000000000000000000000000..3063f71524d98576c13a2178b499fc3db7b94036 --- /dev/null +++ b/ReleaseNotes-2.7.4 @@ -0,0 +1,30 @@ +# +# openSUSE Build Service 2.7.4 +# + +Updaters from OBS 2.7.0 release can just ugrade the packages +and restart all services. Updaters from former releases should +read the README.UPDATERS file. + +This release fixes a few bugs and a security issue caused by to loose API +attribute permission checks. + +Feature backports: +================== + +* none + +Changes: +======== + +* none + +Bugfixes: +========= + +* [api] Fix API permission check for creating and changing (POST) attributes +* [api] Fix API permission check for deleting (DELETE) attributes +* [webui] Invalidate cached session in LDAP mode +* [api][webui] Fail ldap authentification with empty password +* [webui] Fix repository removal when updating project meta fails with an error + diff --git a/src/api/Gemfile.lock b/src/api/Gemfile.lock index c772b0915abaed669b71b22d543bd6aeddb309f5..758e46dd49b49a075c218fa894b2f19e2ce26d52 100644 --- a/src/api/Gemfile.lock +++ b/src/api/Gemfile.lock @@ -1,36 +1,36 @@ GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.5.2) - actionpack (= 4.2.5.2) - actionview (= 4.2.5.2) - activejob (= 4.2.5.2) + actionmailer (4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.5.2) - actionview (= 4.2.5.2) - activesupport (= 4.2.5.2) + actionpack (4.2.7.1) + actionview (= 4.2.7.1) + activesupport (= 4.2.7.1) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - actionview (4.2.5.2) - activesupport (= 4.2.5.2) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.7.1) + activesupport (= 4.2.7.1) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (4.2.5.2) - activesupport (= 4.2.5.2) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.7.1) + activesupport (= 4.2.7.1) globalid (>= 0.3.0) - activemodel (4.2.5.2) - activesupport (= 4.2.5.2) + activemodel (4.2.7.1) + activesupport (= 4.2.7.1) builder (~> 3.1) - activerecord (4.2.5.2) - activemodel (= 4.2.5.2) - activesupport (= 4.2.5.2) + activerecord (4.2.7.1) + activemodel (= 4.2.7.1) + activesupport (= 4.2.7.1) arel (~> 6.0) - activesupport (4.2.5.2) + activesupport (4.2.7.1) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) @@ -184,16 +184,16 @@ GEM rack (1.6.4) rack-test (0.6.3) rack (>= 1.0) - rails (4.2.5.2) - actionmailer (= 4.2.5.2) - actionpack (= 4.2.5.2) - actionview (= 4.2.5.2) - activejob (= 4.2.5.2) - activemodel (= 4.2.5.2) - activerecord (= 4.2.5.2) - activesupport (= 4.2.5.2) + rails (4.2.7.1) + actionmailer (= 4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) + activemodel (= 4.2.7.1) + activerecord (= 4.2.7.1) + activesupport (= 4.2.7.1) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.5.2) + railties (= 4.2.7.1) sprockets-rails rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) @@ -205,9 +205,9 @@ GEM loofah (~> 2.0) rails_tokeninput (1.7.0) railties (>= 3.1.0) - railties (4.2.5.2) - actionpack (= 4.2.5.2) - activesupport (= 4.2.5.2) + railties (4.2.7.1) + actionpack (= 4.2.7.1) + activesupport (= 4.2.7.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.0.0) diff --git a/src/api/app/controllers/attribute_controller.rb b/src/api/app/controllers/attribute_controller.rb index 40e794798c18b427b63b033bd753fa884db6b70a..5f8868ba5b979aeb405184735f66da3c1384a7ce 100644 --- a/src/api/app/controllers/attribute_controller.rb +++ b/src/api/app/controllers/attribute_controller.rb @@ -209,12 +209,10 @@ class AttributeController < ApplicationController render_error :status => 404, :errorcode => "not_found", :message => "Attribute #{params[:attribute]} does not exist" and return end - if params[:attribute] - unless User.current.can_create_attribute_in? @attribute_container, namespace: params[:namespace], name: params[:name] - render_error :status => 403, :errorcode => "change_attribute_no_permission", - :message => "user #{user.login} has no permission to change attribute" - return - end + unless User.current.can_create_attribute_in? @attribute_container, namespace: params[:namespace], name: params[:name] + render_error status: 403, errorcode: "change_attribute_no_permission", + message: "user #{user.login} has no permission to change attribute" + return end # exec @@ -235,26 +233,18 @@ class AttributeController < ApplicationController req = ActiveXML::Node.new(request.raw_post) # checks - if params[:attribute] - unless User.current.can_create_attribute_in? @attribute_container, namespace: params[:namespace], name: params[:name] - render_error :status => 403, :errorcode => "change_attribute_no_permission", - :message => "user #{user.login} has no permission to change attribute" + req.each('attribute') do |attr| + begin + can_create = User.current.can_create_attribute_in? @attribute_container, namespace: attr.value('namespace'), name: attr.value('name') + rescue ArgumentError => e + render_error status: 400, errorcode: "change_attribute_attribute_error", + message: e.message return end - else - req.each('attribute') do |attr| - begin - can_create = User.current.can_create_attribute_in? @attribute_container, namespace: attr.value('namespace'), name: attr.value('name') - 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 + 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 diff --git a/src/api/app/controllers/request_controller.rb b/src/api/app/controllers/request_controller.rb index 828b3be84ac3f05b1da6a9cd2a5cb15bd4ca0a36..acd1dec89a09a84c9327462d6e135a977a5175a6 100644 --- a/src/api/app/controllers/request_controller.rb +++ b/src/api/app/controllers/request_controller.rb @@ -59,7 +59,7 @@ class RequestController < ApplicationController # POST /request?cmd=create def global_command unless %w(create).include? params[:cmd] - raise UnknownCommandError.new "Unknown command '#{params[opt[:cmd_param]]}' for path #{request.path}" + raise UnknownCommandError.new "Unknown command '#{params[:cmd]}' for path #{request.path}" end # refuse request creation for anonymous users diff --git a/src/api/app/controllers/source_controller.rb b/src/api/app/controllers/source_controller.rb index 56f4f9071ee9f08de29bd40de33e4a814e5834c3..2a2150b1987b858274fb472036c7d7c9d8016e64 100644 --- a/src/api/app/controllers/source_controller.rb +++ b/src/api/app/controllers/source_controller.rb @@ -150,7 +150,11 @@ class SourceController < ApplicationController return end project.check_weak_dependencies! - check_and_remove_repositories!(project.repositories, !params[:remove_linking_repositories].blank?, !params[:force].blank?) + opts = { no_write_to_backend: true, + force: params[:force].present?, + recursive_remove: params[:remove_linking_repositories].present? + } + check_and_remove_repositories!(project.repositories, opts) logger.info "destroying project object #{project.name}" project.commit_opts = { comment: params[:comment] } @@ -504,7 +508,11 @@ class SourceController < ApplicationController if project remove_repositories = project.get_removed_repositories(request_data) - check_and_remove_repositories!(remove_repositories, !params[:remove_linking_repositories].blank?, !params[:force].blank?) + opts = { no_write_to_backend: true, + force: params[:force].present?, + recursive_remove: params[:remove_linking_repositories].present? + } + check_and_remove_repositories!(remove_repositories, opts) end Project.transaction do @@ -522,13 +530,14 @@ class SourceController < ApplicationController render_ok end - def check_and_remove_repositories!(repositories, full_remove, force = false) - error = Project.check_repositories(repositories) unless force - if !force && error[:error] + def check_and_remove_repositories!(repositories, opts) + error = Project.check_repositories(repositories) unless opts[:force] + if !opts[:force] && error[:error] raise RepoDependency, error[:error] else - error = Project.remove_repositories(repositories, full_remove) - if !force && error[:error] + error = Project.remove_repositories(repositories, opts) + + if !opts[:force] && error[:error] raise ChangeProjectNoPermission, error[:error] end end @@ -689,10 +698,10 @@ class SourceController < ApplicationController return end - if pkg and not pkg.disabled_for?('sourceaccess', nil, nil) - if FlagHelper.xml_disabled_for?(rdata, 'sourceaccess') - render_error :status => 403, :errorcode => 'change_package_protection_level', - :message => 'admin rights are required to raise the protection level of a package' + if pkg && !pkg.disabled_for?('sourceaccess', nil, nil) + if FlagHelper.xml_disabled_for?(rdata, 'sourceaccess') && !User.current.is_admin? + render_error status: 403, errorcode: 'change_package_protection_level', + message: 'admin rights are required to raise the protection level of a package' return end end diff --git a/src/api/app/controllers/trigger_controller.rb b/src/api/app/controllers/trigger_controller.rb index ca7c6a7b79f16bc75ac1c1b8ee094da81275dda5..d7a060e874eda0920d7070b5379d136606566e9c 100644 --- a/src/api/app/controllers/trigger_controller.rb +++ b/src/api/app/controllers/trigger_controller.rb @@ -27,10 +27,17 @@ class TriggerController < ApplicationController end pkg = token.package + if pkg + # check if user has still access + unless token.user.is_active? && token.user.can_modify_package?(pkg) + raise NoPermission.new "no permission for package #{pkg.name} in project #{pkg.project.name}" + end + end + unless pkg # token is not bound to a package, but event may have specified it pkg = Package.get_by_project_and_name(params[:project].to_s, params[:package].to_s, use_source: true) - unless token.user.can_modify_package? pkg + unless token.user.is_active? && token.user.can_modify_package?(pkg) raise NoPermission.new "no permission for package #{pkg.name} in project #{pkg.project.name}" end end diff --git a/src/api/app/controllers/webui/package_controller.rb b/src/api/app/controllers/webui/package_controller.rb index df92562dd0704843c2458cd28cdb27f34a3b9625..f6f3aa85f0b1c1a80ee559e29a1cf544a3b0ed7e 100644 --- a/src/api/app/controllers/webui/package_controller.rb +++ b/src/api/app/controllers/webui/package_controller.rb @@ -278,6 +278,7 @@ class Webui::PackageController < Webui::WebuiController elsif params[:project].include?(':branches:') opts[:sourceupdate] = 'update' # Avoid auto-removal of branch end + opts[:source_rev] = params[:rev] if params[:rev] action = BsRequestActionSubmit.new(opts) req.bs_request_actions << action action.bs_request = req diff --git a/src/api/app/controllers/webui/project_controller.rb b/src/api/app/controllers/webui/project_controller.rb index 9a02c40cee63487ec514b40495f55f5a1a614738..b9771404ddc4a0be13dc8ea8a095d0358fa24793 100644 --- a/src/api/app/controllers/webui/project_controller.rb +++ b/src/api/app/controllers/webui/project_controller.rb @@ -708,12 +708,13 @@ class Webui::ProjectController < Webui::WebuiController Suse::Validator.validate('project', params[:meta]) request_data = Xmlhash.parse(params[:meta]) + remove_repositories = @project.get_removed_repositories(request_data) + errors << Project.check_repositories(remove_repositories)[:error] errors << Project.validate_remote_permissions(request_data)[:error] errors << Project.validate_link_xml_attribute(request_data, @project.name)[:error] errors << Project.validate_maintenance_xml_attribute(request_data)[:error] errors << Project.validate_repository_xml_attribute(request_data, @project.name)[:error] - errors << @project.check_and_remove_repositories(request_data, !params[:remove_linking_repositories].blank?)[:error] errors = errors.compact if errors.empty? @@ -724,7 +725,7 @@ class Webui::ProjectController < Webui::WebuiController end end - rescue Suse::ValidationError => exception + rescue Suse::ValidationError => exception errors << exception.message rescue Project::UnknownObjectError => exception errors << "Project with name '#{exception.message}' not found" diff --git a/src/api/app/controllers/webui/user_controller.rb b/src/api/app/controllers/webui/user_controller.rb index 5127ca8b3c05e0976e6b2871b27f74a2f1dfbb15..9505fb8e41acbb3bac840c8c9e5e5803c84e8408 100644 --- a/src/api/app/controllers/webui/user_controller.rb +++ b/src/api/app/controllers/webui/user_controller.rb @@ -14,6 +14,7 @@ class Webui::UserController < Webui::WebuiController def logout logger.info "Logging out: #{session[:login]}" + Rails.cache.delete("ldap_cache_userpasswd:#{session[:login]}") reset_session User.current = nil if CONFIG['proxy_auth_mode'] == :on @@ -27,12 +28,22 @@ class Webui::UserController < Webui::WebuiController end def do_login - unless User.authenticate(params[:username], params[:password]) + user = User.find_with_credentials(params[:username], params[:password]) + + if user && !user.is_active? + redirect_to(root_path, error: "Your account is disabled. Please contact the adminsitrator for details.") + return + end + + unless user redirect_to(user_login_path, error: 'Authentication failed') return end - session[:login] = User.current.login + Rails.logger.debug "Authentificated user '#{user.try(:login)}'" + + session[:login] = user.login + User.current = user if request.referer.end_with?("/user/login") redirect_to home_path diff --git a/src/api/app/controllers/webui/webui_controller.rb b/src/api/app/controllers/webui/webui_controller.rb index e65db45dd8066dccf7ac03af1fc95017a3f395a6..8d0468b518c2eee716b9d125755b07d1b0c6723f 100644 --- a/src/api/app/controllers/webui/webui_controller.rb +++ b/src/api/app/controllers/webui/webui_controller.rb @@ -211,7 +211,7 @@ class Webui::WebuiController < ActionController::Base return end - # If the user logs in for the first time (before we have a User with that login) + # The user does not exist in our database, create her. unless User.where(login: user_login).exists? logger.debug "Creating user #{user_login}" chars = ["A".."Z", "a".."z", "0".."9"].collect { |r| r.to_a }.join @@ -224,9 +224,15 @@ class Webui::WebuiController < ActionController::Base password_confirmation: fakepw) end - User.current = User.find_by_login(user_login) + # The user exists, check if shes active and update the info + User.current = User.find_by(login: user_login) + unless User.current.is_active? + session[:login] = nil + User.current = User.find_nobody! + redirect_to(CONFIG['proxy_auth_logout_page'], error: "Your account is disabled. Please contact the adminsitrator for details.") + return + end User.current.update_user_info_from_proxy_env(request.env) - return end User.current = User.find_by_login(session[:login]) if session[:login] diff --git a/src/api/app/models/bs_request_action_maintenance_incident.rb b/src/api/app/models/bs_request_action_maintenance_incident.rb index dee3ff3f01b0ca5bd1bc1c8930ebbe5ff41d24b5..2a664a5652fe23783d3b0d6a04b825c68ee28793 100644 --- a/src/api/app/models/bs_request_action_maintenance_incident.rb +++ b/src/api/app/models/bs_request_action_maintenance_incident.rb @@ -58,7 +58,7 @@ class BsRequestActionMaintenanceIncident < BsRequestAction super(opts) end - def _merge_pkg_into_maintenance_incident(incidentProject, source_project, source_package, releaseproject = nil, request = nil) + def _merge_pkg_into_maintenance_incident(incidentProject) # recreate package based on link target and throw everything away, except source changes # silently as maintenance teams requests ... new_pkg = nil @@ -86,17 +86,17 @@ class BsRequestActionMaintenanceIncident < BsRequestAction end # use specified release project if defined - elsif releaseproject + elsif target_releaseproject package_name = source_package package_name = linkinfo['package'] if linkinfo - branch_params = {:target_project => incidentProject.name, - :olinkrev => 'base', - :maintenance => 1, - :force => 1, - :comment => 'Initial new branch', - :project => releaseproject, :package => package_name} - branch_params[:requestid] = request.id if request + branch_params = {target_project: incidentProject.name, + olinkrev: 'base', + requestid: bs_request.number, + maintenance: 1, + force: 1, + comment: 'Initial new branch', + project: target_releaseproject, package: package_name} # accept branching from former update incidents or GM (for kgraft case) linkprj = Project.find_by_name(linkinfo['project']) if linkinfo if defined?(linkprj) && linkprj @@ -117,13 +117,12 @@ class BsRequestActionMaintenanceIncident < BsRequestAction # linked to an existing package in an external project linked_project = linkinfo['project'] linked_package = linkinfo['package'] - - branch_params = {:target_project => incidentProject.name, - :olinkrev => 'base', - :maintenance => 1, - :force => 1, - :project => linked_project, :package => linked_package} - branch_params[:requestid] = request.id if request + branch_params = {target_project: incidentProject.name, + olinkrev: 'base', + requestid: bs_request.number, + maintenance: 1, + force: 1, + project: linked_project, package: linked_package} ret = BranchPackage.new(branch_params).branch new_pkg = Package.get_by_project_and_name(ret[:data][:targetproject], ret[:data][:targetpackage]) else @@ -142,21 +141,22 @@ class BsRequestActionMaintenanceIncident < BsRequestAction end end - # backend copy of current sources, but keep link + # backend copy of submitted sources, but keep link cp_params = { cmd: "copy", user: User.current.login, oproject: source_project, opackage: source_package, + requestid: bs_request.number, keeplink: 1, expand: 1, withacceptinfo: 1, comment: "Maintenance incident copy from project #{source_project}" } - cp_params[:requestid] = request.number if request + cp_params[:orev] = source_rev if source_rev cp_path = "/source/#{CGI.escape(incidentProject.name)}/#{CGI.escape(new_pkg.name)}" cp_path << Suse::Backend.build_query_from_hash(cp_params, [:cmd, :user, :oproject, :opackage, - :keeplink, :expand, :comment, + :orev, :keeplink, :expand, :comment, :requestid, :withacceptinfo]) result = Suse::Backend.post cp_path, nil result = Xmlhash.parse(result.body) @@ -166,10 +166,10 @@ class BsRequestActionMaintenanceIncident < BsRequestAction new_pkg end - def merge_into_maintenance_incident(incidentProject, source_project, source_package, releaseproject = nil, request = nil) + def merge_into_maintenance_incident(incidentProject) # copy all or selected packages and project source files from base project # we don't branch from it to keep the link target. - pkg = _merge_pkg_into_maintenance_incident(incidentProject, source_project, source_package, releaseproject, request) + pkg = _merge_pkg_into_maintenance_incident(incidentProject) incidentProject.save! incidentProject.store(comment: "maintenance_incident request #{self.bs_request.number}", request: self.bs_request) @@ -181,9 +181,7 @@ class BsRequestActionMaintenanceIncident < BsRequestAction incident_project = Project.get_by_name(self.target_project) # the incident got created before - self.target_package = merge_into_maintenance_incident(incident_project, - self.source_project, self.source_package, - self.target_releaseproject, self.bs_request) + self.target_package = merge_into_maintenance_incident(incident_project) # update action with real target project self.target_project = incident_project.name diff --git a/src/api/app/models/bs_request_permission_check.rb b/src/api/app/models/bs_request_permission_check.rb index 721553f2cedd6d675a9be163fe504fefeb9ff660..f644a316c9a8d50ad8b3e1c4da3a550ab584a255 100644 --- a/src/api/app/models/bs_request_permission_check.rb +++ b/src/api/app/models/bs_request_permission_check.rb @@ -171,7 +171,7 @@ class BsRequestPermissionCheck end end - def set_permissions_for_action(action) + def set_permissions_for_action(action, new_state = nil) # general write permission check on the target on accept @write_permission_in_this_action = false @@ -192,6 +192,12 @@ class BsRequestPermissionCheck end end + if action.action_type == :maintenance_incident + # this action type is always branching using extended names + target_package_name = Package.extended_name(action.source_project, action.source_package) + @target_package = @target_project.packages.find_by_name(target_package_name) + end + # general source write permission check (for revoke) if (@source_package and User.current.can_modify_package?(@source_package, true)) or (not @source_package and @source_project and User.current.can_modify_project?(@source_project, true)) @@ -201,7 +207,8 @@ class BsRequestPermissionCheck # general write permission check on the target on accept @write_permission_in_this_action = false # meta data change shall also be allowed after freezing a project using force: - ignoreLock = opts[:force] and [:set_bugowner].include? action.action_type + ignoreLock = (new_state == "declined") || + (opts[:force] && action.action_type == :set_bugowner) if @target_package if User.current.can_modify_package?(@target_package, ignoreLock) @write_permission_in_target = true @@ -349,7 +356,7 @@ class BsRequestPermissionCheck # permission and validation check for each action inside req.bs_request_actions.each do |action| - set_permissions_for_action(action) + set_permissions_for_action(action, opts[:newstate]) check_newstate_action! action, opts diff --git a/src/api/app/models/package.rb b/src/api/app/models/package.rb index f2fb142438c2eedc822f60b3378b1587986e38b6..99b024a82e70b4f0d71726fdf1c979a76172de94 100644 --- a/src/api/app/models/package.rb +++ b/src/api/app/models/package.rb @@ -839,6 +839,14 @@ class Package < ActiveRecord::Base return BsRequest.where(id: rel.pluck('bs_requests.id')) end + def self.extended_name(project, package) + # the package name which will be used on a branch with extended or maintenance option + directory_hash = Directory.hashed(project: project, package: package) + linkinfo = directory_hash["linkinfo"] || {} + + "#{linkinfo['package'] || package}.#{linkinfo['project'] || project}".gsub(/:/, '_') + end + def linkinfo dir_hash['linkinfo'] end diff --git a/src/api/app/models/project.rb b/src/api/app/models/project.rb index 389cc02729f532caa1e29b011b65c1383baa89d8..bfcb1a145a349ed0fd0b33279ec477b3e8a80ee6 100644 --- a/src/api/app/models/project.rb +++ b/src/api/app/models/project.rb @@ -527,18 +527,18 @@ class Project < ActiveRecord::Base # check for raising read access permissions, which can't get ensured atm unless self.new_record? || self.disabled_for?('access', nil, nil) - if FlagHelper.xml_disabled_for?(xmlhash, 'access') + if FlagHelper.xml_disabled_for?(xmlhash, 'access') && !User.current.is_admin? raise ForbiddenError.new end end unless self.new_record? || self.disabled_for?('sourceaccess', nil, nil) - if FlagHelper.xml_disabled_for?(xmlhash, 'sourceaccess') + if FlagHelper.xml_disabled_for?(xmlhash, 'sourceaccess') && !User.current.is_admin? raise ForbiddenError.new end end new_record = self.new_record? - if ::Configuration.default_access_disabled == true and not new_record - if self.disabled_for?('access', nil, nil) and not FlagHelper.xml_disabled_for?(xmlhash, 'access') + if ::Configuration.default_access_disabled == true && !new_record + if self.disabled_for?('access', nil, nil) && !FlagHelper.xml_disabled_for?(xmlhash, 'access') && !User.current.is_admin? raise ForbiddenError.new end end @@ -1728,16 +1728,6 @@ class Project < ActiveRecord::Base {} end - def check_and_remove_repositories(request_data, full_remove = false) - remove_repositories = get_removed_repositories(request_data) - error = Project.check_repositories(remove_repositories) - - return error if error[:error] - - error = Project.remove_repositories(remove_repositories, full_remove) - error[:error] ? error : {} - end - def get_removed_repositories(request_data) new_repositories = request_data.elements('repository').map(&:values).flatten old_repositories = repositories.all.map(&:name) @@ -1773,7 +1763,8 @@ class Project < ActiveRecord::Base {} end - def self.remove_repositories(repositories, full_remove = false) + # opts: recursive_remove no_write_to_backend + def self.remove_repositories(repositories, opts = {}) deleted_repository = Repository.deleted_instance repositories.each do |repo| @@ -1781,10 +1772,13 @@ class Project < ActiveRecord::Base project = repo.project # full remove, otherwise the model will take care of the cleanup - if full_remove + if opts[:recursive_remove] # recursive for INDIRECT linked repositories unless linking_repositories.length < 1 - Project.remove_repositories(linking_repositories, true) + # FIXME: we would actually need to check for :no_write_to_backend here as well + # but the calling code is currently broken and would need the starting + # project different + Project.remove_repositories(linking_repositories, {recursive_remove: true}) end # try to remove the repository @@ -1802,7 +1796,7 @@ class Project < ActiveRecord::Base if Repository.exists?(repo.id) && repository logger.info "destroy repo #{repository.name} in '#{project.name}'" repository.destroy - project.store({ lowprio: true }) # low prio storage + project.store({ lowprio: true }) unless opts[:no_write_to_backend] end end {} diff --git a/src/api/app/models/token.rb b/src/api/app/models/token.rb index 6fea6218b8d91c6a8f39043173f4e840c0c1f97e..040faecf89cc7c26bb124dbd85b6faab5a939468 100644 --- a/src/api/app/models/token.rb +++ b/src/api/app/models/token.rb @@ -8,11 +8,6 @@ class Token < ActiveRecord::Base def self.find_by_string(token) token = Token.where(string: token.to_s).includes(:package, :user).first return nil unless token and token.user_id - # is token bound to a package? - if token.package - # check if user has still access - return nil unless token.user.can_modify_package? token.package - end # package found and user has write access return token diff --git a/src/api/app/models/user_ldap_strategy.rb b/src/api/app/models/user_ldap_strategy.rb index b346ff0bc91d9f3d2d25eb27ba827eae84c665f7..81176f710629727892781af83f8bf234481108a4 100644 --- a/src/api/app/models/user_ldap_strategy.rb +++ b/src/api/app/models/user_ldap_strategy.rb @@ -452,6 +452,9 @@ class UserLdapStrategy return nil end when :ldap then + # ruby-ldap returns true if password is empty + # https://github.com/ruby-ldap/ruby-net-ldap/issues/5 + return unless password.present? # Don't match the passwd locally, try to bind to the ldap server user_con= initialize_ldap_con(user['dn'], password) if user_con.nil? diff --git a/src/api/config/options.yml.example b/src/api/config/options.yml.example index 045b040248cc4209e050d3fe02cf328a3a6cbb30..3ae0a47f154f253e9343d891d205bf15b9714d0b 100644 --- a/src/api/config/options.yml.example +++ b/src/api/config/options.yml.example @@ -62,7 +62,9 @@ proxy_auth_test_email: coolguy@example.com # LDAP options ################## +#### WARNING: LDAP mode is not official supported by OBS! ldap_mode: :off +#### WARNING: LDAP mode is not official supported by OBS! # LDAP Servers separated by ':'. # OVERRIDE with your company's ldap servers. Servers are picked randomly for diff --git a/src/api/db/migrate/20160824132643_fix_bs_request_counter.rb b/src/api/db/migrate/20160824132643_fix_bs_request_counter.rb new file mode 100644 index 0000000000000000000000000000000000000000..25dbd6d38502a3f593b1461f24b82785560f600b --- /dev/null +++ b/src/api/db/migrate/20160824132643_fix_bs_request_counter.rb @@ -0,0 +1,18 @@ +class FixBsRequestCounter < ActiveRecord::Migration + class TempBsRequest < ActiveRecord::Base + self.table_name = 'bs_requests' + end + + class TempBsRequestCounter < ActiveRecord::Base + self.table_name = 'bs_request_counter' + end + + def change + # BsRequestCounter is not set correctly + # Introduced with 20160321105300_request_counter.rb + # See https://github.com/openSUSE/open-build-service/issues/2068 + counter = TempBsRequest.reorder(:number).pluck(:number).last || 0 + TempBsRequestCounter.destroy_all + TempBsRequestCounter.create!(counter: counter + 1) + end +end diff --git a/src/api/db/structure.sql b/src/api/db/structure.sql index 0222b2021ea0f77cac4e65c0a3c182ba06b0a8b0..88a174effeb9c0e682aa277420fbca403c315b7f 100644 --- a/src/api/db/structure.sql +++ b/src/api/db/structure.sql @@ -1680,6 +1680,8 @@ INSERT INTO schema_migrations (version) VALUES ('20160321105300'); INSERT INTO schema_migrations (version) VALUES ('20160518105300'); +INSERT INTO schema_migrations (version) VALUES ('20160824132643'); + INSERT INTO schema_migrations (version) VALUES ('21'); INSERT INTO schema_migrations (version) VALUES ('22'); diff --git a/src/api/spec/controllers/webui/user_controller_spec.rb b/src/api/spec/controllers/webui/user_controller_spec.rb index a14d97910bfc6ad310b625b8aadc622abacc21f1..4a9fe52879373f9e309df4dad0908c63b130891e 100644 --- a/src/api/spec/controllers/webui/user_controller_spec.rb +++ b/src/api/spec/controllers/webui/user_controller_spec.rb @@ -70,10 +70,31 @@ RSpec.describe Webui::UserController do describe "POST #do_login" do before do request.env["HTTP_REFERER"] = search_url # Needed for the redirect_to :back + end + + it 'logs in users with correct credentials' do post :do_login, {username: user.login, password: 'buildservice'} + expect(response).to redirect_to search_url end - it { expect(response).to redirect_to search_url } + it 'tells users about wrong credentials' do + post :do_login, {username: user.login, password: 'password123'} + expect(response).to redirect_to user_login_path + expect(flash[:error]).to eq("Authentication failed") + end + + it 'tells users about wrong state' do + user.update_attribute('state', User::STATES['locked']) + post :do_login, {username: user.login, password: 'buildservice'} + expect(response).to redirect_to root_path + expect(flash[:error]).to eq("Your account is disabled. Please contact the adminsitrator for details.") + end + + it 'assigns the current user' do + post :do_login, {username: user.login, password: 'buildservice'} + expect(User.current).to eq(user) + expect(session[:login]).to eq(user.login) + end end describe "GET #home" do diff --git a/src/api/test/fixtures/path_elements.yml b/src/api/test/fixtures/path_elements.yml index fc0f08989a5b0ec4898a090f9ea66202ae01a873..d6b16dc3373dcb37fbcebcf86dba7707e9d21623 100644 --- a/src/api/test/fixtures/path_elements.yml +++ b/src/api/test/fixtures/path_elements.yml @@ -30,3 +30,7 @@ UseRemoteInstance_pop_path: parent_id: BaseDistro_repo repository_id: UseRemoteInstance_pop position: 1 +kde4_repo: + parent_id: 98 + repository_id: 86 + position: 1 diff --git a/src/api/test/fixtures/repositories.yml b/src/api/test/fixtures/repositories.yml index e1713c8cf2f041625f27c30dc23c31438ba1e1cc..de44fa8f664cb59f10f9196907b085bc11539814 100644 --- a/src/api/test/fixtures/repositories.yml +++ b/src/api/test/fixtures/repositories.yml @@ -84,3 +84,7 @@ repositories_97: id: 97 name: BrokenPublishing_repo project: BrokenPublishing +kde4_standard: + id: 98 + name: kde4_standard + project: kde4 diff --git a/src/api/test/fixtures/repository_architectures.yml b/src/api/test/fixtures/repository_architectures.yml index 24895e429ce3103fd2a2389f0b34d21fd8bd43cb..ec912acec4ed1a9dfa39c7f92e887860bfde950e 100644 --- a/src/api/test/fixtures/repository_architectures.yml +++ b/src/api/test/fixtures/repository_architectures.yml @@ -122,3 +122,8 @@ repository_architectures_broken_publishing: position: 0 id: 940713216 architecture: i586 +kde4_repo_arch: + repository_id: 98 + position: 0 + id: 940713217 + architecture: s390 diff --git a/src/api/test/functional/attributes_test.rb b/src/api/test/functional/attributes_test.rb index e2271faf35c6abfef993201e910b177900a958b3..c0ff74b74ff974dd4cedda295257c7963b867557 100644 --- a/src/api/test/functional/attributes_test.rb +++ b/src/api/test/functional/attributes_test.rb @@ -260,6 +260,33 @@ ription</description> assert_response 404 end + def test_attrib_write_permissions + login_tom + + data = "<attributes><attribute namespace='OBS' name='VeryImportantProject'/></attributes>" + + # XML with an attribute I should not be able to create + post "/source/home:tom/_attribute", data + assert_response 403 + # same with attribute parameter + post "/source/home:tom/_attribute/OBS:Issues", data + assert_response 403 + end + + def test_attrib_delete_permissions + # create an admin only attribute + login_king + data = "<attributes><attribute namespace='OBS' name='VeryImportantProject'/></attributes>" + post "/source/home:tom/_attribute", data + assert_response :success + + login_tom + delete "/source/home:tom/_attribute/OBS:VeryImportantProject" + assert_response 403 + delete "/source/home:tom/_attribute/?namespace=OBS&name=VeryImportantProject" + assert_response 403 + end + def test_create_attributes_project login_tom diff --git a/src/api/test/functional/channel_maintenance_test.rb b/src/api/test/functional/channel_maintenance_test.rb index 4a42c19eaafc2bc06aeab720e8dd61d38632b7dd..25a14f511b10870afa4d6f645e835867b1419a79 100644 --- a/src/api/test/functional/channel_maintenance_test.rb +++ b/src/api/test/functional/channel_maintenance_test.rb @@ -152,7 +152,8 @@ class ChannelMaintenanceTests < ActionDispatch::IntegrationTest assert_response :success # create maintenance request with invalid target - post '/request?cmd=create', '<request> + login_tom + post '/request?cmd=create&addrevision=1', '<request> <action type="maintenance_incident"> <source project="home:tom:branches:OBS_Maintained:pack2" package="pack2.BaseDistro2.0_LinkedUpdateProject" /> <target project="home:tom" /> @@ -161,7 +162,7 @@ class ChannelMaintenanceTests < ActionDispatch::IntegrationTest assert_response 400 assert_xml_tag :tag => 'status', :attributes => { code: 'no_maintenance_project' } # valid target.. - post '/request?cmd=create', '<request> + post '/request?cmd=create&addrevision=1', '<request> <action type="maintenance_incident"> <source project="home:tom:branches:OBS_Maintained:pack2" package="pack2.BaseDistro2.0_LinkedUpdateProject" /> <target project="'+incidentProject+'" /> @@ -178,7 +179,7 @@ class ChannelMaintenanceTests < ActionDispatch::IntegrationTest # create maintenance request for two further packages # without specifing target, the default target must get found via attribute - post '/request?cmd=create', '<request> + post '/request?cmd=create&addrevision=1', '<request> <action type="maintenance_incident"> <source project="home:tom:branches:OBS_Maintained:pack2" package="pack2.BaseDistro2.0_LinkedUpdateProject" /> </action> @@ -193,7 +194,7 @@ class ChannelMaintenanceTests < ActionDispatch::IntegrationTest node = ActiveXML::Node.new(@response.body) assert node.has_attribute?(:id) id2 = node.value(:id) - post '/request?cmd=create', '<request> + post '/request?cmd=create&addrevision=1', '<request> <action type="maintenance_incident"> <source project="home:tom:branches:OBS_Maintained:pack2" package="pack2.BaseDistro2.0_LinkedUpdateProject" /> </action> @@ -540,7 +541,8 @@ class ChannelMaintenanceTests < ActionDispatch::IntegrationTest node = ActiveXML::Node.new(@response.body) assert node.has_attribute?(:id) reqid = node.value(:id) - # revoke try new request + + # revoke the release request request post "/request/#{reqid}?cmd=changestate&newstate=revoked" assert_response :success diff --git a/src/api/test/functional/maintenance_test.rb b/src/api/test/functional/maintenance_test.rb index bc170b45c442e35d13b9dedab5d93cd6c0584727..45b4444e8dfe759be3a0428805905bd637ef1484 100644 --- a/src/api/test/functional/maintenance_test.rb +++ b/src/api/test/functional/maintenance_test.rb @@ -206,7 +206,7 @@ class MaintenanceTests < ActionDispatch::IntegrationTest <state name="new" /> </request>' assert_response :success - post '/request?cmd=create', '<request> + post '/request?cmd=create&addrevision=1', '<request> <action type="maintenance_incident"> <source project="RemoteInstance:kde4" package="kdelibs" /> <target project="My:Maintenance" releaseproject="BaseDistro2.0:LinkedUpdateProject" /> @@ -220,6 +220,12 @@ class MaintenanceTests < ActionDispatch::IntegrationTest assert node.has_attribute?(:id) id1 = node.value(:id) + # modify source afterwards, must not appear in target after accept + login_king + put "/source/kde4/kdelibs/TEMP_FILE", "dummy" + assert_response :success + login_tom + # validate that request is diffable (not broken) post "/request/#{id1}?cmd=diff&view=xml", nil assert_response :success @@ -245,7 +251,9 @@ class MaintenanceTests < ActionDispatch::IntegrationTest get "/source/#{incidentProject}/kdelibs.BaseDistro2.0_LinkedUpdateProject" assert_response :success - assert_xml_tag( :tag => 'linkinfo', :attributes => { project: 'BaseDistro2.0:LinkedUpdateProject', package: 'kdelibs' } ) + assert_xml_tag( tag: 'linkinfo', attributes: { project: 'BaseDistro2.0:LinkedUpdateProject', package: 'kdelibs' } ) + get "/source/#{incidentProject}/kdelibs.BaseDistro2.0_LinkedUpdateProject/TEMP_FILE" + assert_response 404 # no patchinfo was part in source project, got it created ? get "/source/#{incidentProject}/patchinfo/_patchinfo" @@ -338,6 +346,8 @@ class MaintenanceTests < ActionDispatch::IntegrationTest assert_response :success delete '/source/BaseDistro2.0:LinkedUpdateProject/kdelibs' assert_response :success + delete "/source/kde4/kdelibs/TEMP_FILE" + assert_response :success end def test_OBS_BranchTarget @@ -599,7 +609,10 @@ class MaintenanceTests < ActionDispatch::IntegrationTest assert_no_xml_tag :parent => { tag: 'issue' }, :tag => 'issue', :attributes => { change: '' } assert_xml_tag :parent => { tag: 'issue', attributes: { change: 'added' } }, :tag => 'name', :content => '1042' - post '/source', :cmd => 'branch', :package => 'kdelibs', :target_project => 'home:tom:branches:OBS_Maintained:pack2' + get '/source/home:tom:branches:OBS_Maintained:pack2/_meta' + assert_response :success + oldmeta = @response.body + post '/source', cmd: 'branch', package: 'kdelibs', target_project: 'home:tom:branches:OBS_Maintained:pack2' assert_response :success get '/source/home:tom:branches:OBS_Maintained:pack2/kdelibs.kde4/_link' assert_response :success @@ -658,6 +671,8 @@ class MaintenanceTests < ActionDispatch::IntegrationTest # delete kdelibs package again or incident creation will fail since it does not point to a maintained project. delete '/source/home:tom:branches:OBS_Maintained:pack2/kdelibs.kde4' assert_response :success + put '/source/home:tom:branches:OBS_Maintained:pack2/_meta', oldmeta + assert_response :success # create maintenance request # without specifing target, the default target must get found via attribute @@ -689,8 +704,8 @@ class MaintenanceTests < ActionDispatch::IntegrationTest # store data for later checks get '/source/home:tom:branches:OBS_Maintained:pack2/_meta' - oprojectmeta = ActiveXML::Node.new(@response.body) assert_response :success + oprojectmeta = ActiveXML::Node.new(@response.body) get "/source/home:tom:branches:OBS_Maintained:pack2/_meta" assert_response :success diff --git a/src/api/test/functional/read_permission_test.rb b/src/api/test/functional/read_permission_test.rb index 0859a0ce496381416a7d820f63c9a35f85b40c60..3e2c4db37b515ca487efd3363a22e157cc3491d9 100644 --- a/src/api/test/functional/read_permission_test.rb +++ b/src/api/test/functional/read_permission_test.rb @@ -502,7 +502,12 @@ class ReadPermissionTest < ActionDispatch::IntegrationTest put url_for(:controller => :source, :action => :update_package_meta, :project => "home:adrian:PublicProject", :package => "pack"), '<package name="pack" project="home:adrian:PublicProject"> <title/> <description/> <sourceaccess><disable/></sourceaccess> </package>' assert_response 403 - assert_xml_tag :tag => "status", :attributes => { :code => "change_package_protection_level" } + assert_xml_tag tag: "status", attributes: { code: "change_package_protection_level" } + # but works as admin + login_king + put url_for(controller: :source, action: :update_package_meta, project: "home:adrian:PublicProject", package: "pack"), + '<package name="pack" project="home:adrian:PublicProject"> <title/> <description/> <sourceaccess><disable/></sourceaccess> </package>' + assert_response :success delete "/source/home:adrian:Project" assert_response :success delete "/source/home:adrian:PublicProject" @@ -518,7 +523,11 @@ class ReadPermissionTest < ActionDispatch::IntegrationTest put url_for(:controller => :source, :action => :update_project_meta, :project => "home:adrian:Project"), '<project name="home:adrian:Project"> <title/> <description/> <access><disable/></access> </project>' assert_response 403 - assert_xml_tag :tag => "status", :attributes => { :code => "change_project_protection_level" } + assert_xml_tag tag: "status", attributes: { code: "change_project_protection_level" } + login_king + put url_for(controller: :source, action: :update_project_meta, project: "home:adrian:Project"), + '<project name="home:adrian:Project"> <title/> <description/> <access><disable/></access> </project>' + assert_response :success delete "/source/home:adrian:Project" assert_response :success end diff --git a/src/api/test/functional/release_management_test.rb b/src/api/test/functional/release_management_test.rb index 41843a4ea99f399d4d08ef97a0d8275feb417a85..741fc85d590c24a0b28dab16382913d0d8708d50 100644 --- a/src/api/test/functional/release_management_test.rb +++ b/src/api/test/functional/release_management_test.rb @@ -6,11 +6,10 @@ class ReleaseManagementTests < ActionDispatch::IntegrationTest def setup reset_auth + wait_for_scheduler_start end def test_move_entire_project - wait_for_scheduler_start - login_tom # try as non-admin @@ -152,4 +151,106 @@ class ReleaseManagementTests < ActionDispatch::IntegrationTest delete "/source/TEST:BaseDistro" assert_response :success end + + def test_copy_project_withbinaries + login_king + + run_scheduler('i586') + run_scheduler('x86_64') + inject_build_job( 'home:Iggy', 'TestPack', '10.2', 'i586') + inject_build_job( 'home:Iggy', 'TestPack', '10.2', 'x86_64') + run_scheduler('i586') + run_scheduler('x86_64') + run_publisher + + # prerequisite: is our source project setup correctly? + get '/build/home:Iggy/10.2/i586/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 4 } + get '/build/home:Iggy/10.2/x86_64/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 5 } + + # our source project is not building + get '/build/home:Iggy/_result' + assert_xml_tag :parent => { tag: 'result', + :attributes => { project: 'home:Iggy', + repository: '10.2', + arch: 'i586', + code: 'published', + state: 'published' } + }, + tag: 'status', + :attributes => { package: 'TestPack', + code: 'succeeded' } + assert_xml_tag :parent => { + tag: 'result', + :attributes => { project: 'home:Iggy', + repository: '10.2', + arch: 'x86_64', + code: 'published', + state: 'published' } }, + :tag => 'status', :attributes => { package: 'TestPack', + code: 'succeeded' } + + # copy project with binaries + post '/source/IggyHomeCopy?cmd=copy&oproject=home:Iggy&noservice=1&withbinaries=1&nodelay=1' + assert_response :success + + # let scheduler process events... + run_scheduler('i586') + run_scheduler('x86_64') + run_publisher + + # get copy project meta and verify copied repositories + get '/source/IggyHomeCopy/_meta' + assert_response :success + + assert_xml_tag :parent => { :tag => 'project', :attributes => { :name => 'IggyHomeCopy' } }, + :tag => 'repository', :attributes => { :name => '10.2' } + + assert_xml_tag :parent => { :tag => 'repository', :attributes => { :name => '10.2' } }, + :tag => 'path', :attributes => { :project => 'BaseDistro', :repository => 'BaseDistro_repo' } + + assert_xml_tag :parent => { :tag => 'repository', :attributes => { :name => '10.2' } }, + :tag => 'arch', :content => 'i586' + + assert_xml_tag :parent => { :tag => 'repository', :attributes => { :name => '10.2' } }, + :tag => 'arch', :content => 'x86_64' + + # check build results are copied correctly + get '/build/IggyHomeCopy/_result' + assert_xml_tag :parent => { + tag: 'result', + :attributes => { project: 'IggyHomeCopy', + repository: '10.2', + arch: 'i586', + code: 'published', + state: 'published' } }, + tag: 'status', + :attributes => { package: 'TestPack', code: 'succeeded' } + + assert_xml_tag :parent => { + tag: 'result', + :attributes => { project: 'IggyHomeCopy', + repository: '10.2', + arch: 'x86_64', + code: 'published', + state: 'published' } + }, + tag: 'status', + :attributes => { package: 'TestPack', code: 'succeeded' } + + # check that the same binaries are copied + get '/build/home:Iggy/10.2/i586/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 4 } + get '/build/IggyHomeCopy/10.2/i586/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 4 } + get '/build/home:Iggy/10.2/x86_64/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 5 } + get '/build/IggyHomeCopy/10.2/x86_64/TestPack' + assert_xml_tag :tag => 'binarylist', :children => { :count => 5 } + + # cleanup + delete '/source/IggyHomeCopy' + assert_response :success + end end diff --git a/src/api/test/functional/request_controller_test.rb b/src/api/test/functional/request_controller_test.rb index 84caf8c9de215c4d7908481409178fe0b8c8e838..d2629decd1f778504b8b70db72d73e670095d997 100644 --- a/src/api/test/functional/request_controller_test.rb +++ b/src/api/test/functional/request_controller_test.rb @@ -1,5 +1,6 @@ # encoding: UTF-8 # rubocop:disable Metrics/LineLength +# rubocop:disable Metrics/ClassLength require File.expand_path(File.dirname(__FILE__) + '/..') + '/test_helper' require 'request_controller' @@ -53,6 +54,15 @@ XML end end + def test_invalid_command + post '/request?cmd=INVALID' + assert_response 401 + login_king + post '/request?cmd=INVALID' + assert_response 400 + assert_xml_tag(tag: 'status', attributes: { code: 'unknown_command' }) + end + def test_get_requests_collection login_king get '/request', view: 'collection', reviewstates: 'accepted' @@ -1526,10 +1536,10 @@ XML # id2 = node.value(:id) # delete projects - delete '/source/home:tom:branches:kde4' - assert_response :success delete '/source/home:tom:branches:home:tom:branches:kde4' assert_response :success + delete '/source/home:tom:branches:kde4' + assert_response :success # request got automatically revoked get "/request/#{id1}" diff --git a/src/api/test/functional/source_controller_test.rb b/src/api/test/functional/source_controller_test.rb index c5259b9c43886753a272e49afd90585571cf6747..45145aa7b0acb75e50c08d3c3b6ffa588e97981e 100644 --- a/src/api/test/functional/source_controller_test.rb +++ b/src/api/test/functional/source_controller_test.rb @@ -333,7 +333,7 @@ class SourceControllerTest < ActionDispatch::IntegrationTest # Change description xml = @response.body - new_desc = 'Changed description' + new_desc = 'Changed description 1' doc = ActiveXML::Node.new(xml) d = doc.find_first('description') d.text = new_desc @@ -583,7 +583,7 @@ class SourceControllerTest < ActionDispatch::IntegrationTest # Change description xml = @response.body - new_desc = 'Changed description' + new_desc = 'Changed description 2' doc = REXML::Document.new(xml) d = doc.elements['//description'] d.text = new_desc @@ -848,13 +848,12 @@ class SourceControllerTest < ActionDispatch::IntegrationTest def test_put_package_meta_with_invalid_permissions login_tom # The user is valid, but has weak permissions - - get url_for(:controller => :source, :action => :show_package_meta, :project => 'kde4', :package => 'kdelibs') + get url_for(controller: :source, action: :show_package_meta, project: 'kde4', package: 'kdelibs') assert_response :success # Change description xml = @response.body - new_desc = 'Changed description' + new_desc = 'Changed description 4' olddoc = REXML::Document.new(xml) doc = REXML::Document.new(xml) d = doc.elements['//description'] @@ -907,7 +906,7 @@ class SourceControllerTest < ActionDispatch::IntegrationTest end # Change description xml = @response.body - new_desc = 'Changed description' + new_desc = 'Changed description 3' doc = REXML::Document.new(xml) d = doc.elements['//description'] d.text = new_desc @@ -1786,6 +1785,18 @@ class SourceControllerTest < ActionDispatch::IntegrationTest assert_response :success # delete entire project + prepare_request_with_user 'fredlibs', 'buildservice' + get '/source/kde4/_meta' + assert_response :success + meta_before_delete = @response.body + # kind of stupid, but do_change_project_meta_test modifies backend data and does not clean up + put '/source/kde4/_meta', meta_before_delete + assert_response :success + get '/source/kde4/_project/_history?meta=1' + assert_response :success + node = ActiveXML::Node.new(@response.body) + revision = node.each(:revision).last.value :rev + expected_revision = revision.to_i + 1 delete '/source/kde4?user=illegal&comment=drop%20project' assert_response :success @@ -1816,9 +1827,13 @@ class SourceControllerTest < ActionDispatch::IntegrationTest assert_xml_tag(:parent => { :tag => 'revision' }, :tag => 'user', :content => 'fredlibs') assert_xml_tag(:parent => { :tag => 'revision' }, :tag => 'comment', :content => 'drop project') get '/source/kde4/_project/_history?meta=1&deleted=1' - assert_xml_tag(:parent => { :tag => 'revision' }, :tag => 'user', :content => 'fredlibs') - assert_xml_tag(:parent => { :tag => 'revision' }, :tag => 'comment', :content => 'drop project') assert_response :success + assert_xml_tag(parent: { tag: 'revision' }, tag: 'user', content: 'fredlibs') + assert_xml_tag(parent: { tag: 'revision' }, tag: 'comment', content: 'drop project') + # there must be only one change + node = ActiveXML::Node.new(@response.body) + revision = node.each(:revision).last.value :rev + assert_equal expected_revision, revision.to_i prepare_request_with_user 'fredlibs', 'buildservice' # undelete project @@ -1833,10 +1848,10 @@ class SourceControllerTest < ActionDispatch::IntegrationTest get '/source/kde4' assert_response :success get '/source/kde4/_project' - assert_response :success get '/source/kde4/_meta' assert_response :success + assert_equal meta_before_delete, @response.body get '/source/kde4/kdelibs' assert_response :success get '/source/kde4/kdelibs/_meta' diff --git a/src/api/test/functional/source_services_test.rb b/src/api/test/functional/source_services_test.rb index e2f1882a1999d355d53a059b56df736a4f972cb0..531d7dc53fdfd1f2dbb37e573386aae2e1fcc212 100644 --- a/src/api/test/functional/source_services_test.rb +++ b/src/api/test/functional/source_services_test.rb @@ -534,7 +534,24 @@ class SourceServicesTest < ActionDispatch::IntegrationTest assert_response 404 assert_match(/no source service defined/, @response.body) - # and drop stuff as tom + # Locking user blocks the trigger + tom = User.find_by_login("tom") + tom.state = User::STATES['locked'] + tom.save! + # with right token + post '/trigger/runservice', nil, { 'Authorization' => "Token #{token}" } + # success, but no source service configured :) + assert_response 403 + assert_xml_tag tag: "status", attributes: { code: "no_permission" } + # with global token + post '/trigger/runservice?project=home:tom&package=service', nil, { 'Authorization' => "Token #{alltoken}" } + # success, but no source service configured :) + assert_response 403 + assert_xml_tag tag: "status", attributes: { code: "no_permission" } + + # reset and drop stuff as tom + tom.state = User::STATES['confirmed'] + tom.save! login_tom get '/person/tom/token' assert_response :success diff --git a/src/api/test/functional/webui/download_on_demand_controller_test.rb b/src/api/test/functional/webui/download_on_demand_controller_test.rb index a709570cb010995880f179a2432a975b1c77c7f9..5c7f77393683fcdd53d5049f8031eae066423b18 100644 --- a/src/api/test/functional/webui/download_on_demand_controller_test.rb +++ b/src/api/test/functional/webui/download_on_demand_controller_test.rb @@ -46,109 +46,4 @@ class Webui::DownloadOnDemandControllerTest < Webui::IntegrationTest page.wont_have_link 'http://mola.org2' page.wont_have_text 'rpmmd' end - - def test_adding_download_on_demand # spec/features/webui/projects_spec.rb - use_js - - # Login as admin - login_king - visit(project_repositories_path(project: "home:user5")) - click_link("Add DoD repository") - - # Fill in the form and send a working dod data - fill_in("Repository name", with: "My DoD repository") - select('i586', from: 'Architecture') - select('rpmmd', from: 'Type') - fill_in('Url', with: 'http://somerandomurl.es') - fill_in('Arch. Filter', with: 'i586, noarch') - fill_in('Master Url', with: 'http://somerandomurl2.es') - fill_in('SSL Fingerprint', with: '293470239742093') - fill_in('Public Key', with: 'JLKSDJFSJ83U4902RKLJSDFLJF2J9IJ23OJFKJFSDF') - click_button('Save') - - within "#repository-list" do - find(:xpath, "//a[@href='/project/repository_state/home:user5/My%20DoD%20repository']").must_have_text("My DoD repository") - find_link('Add') - find(".edit-dod-repository-link-container").must_have_link('Edit') - find(".edit-dod-repository-link-container").must_have_link('Delete') - page.must_have_link 'http://somerandomurl.es' - page.must_have_text 'rpmmd' - end - - click_link("Repositories") - click_link("Add") - - # Fill in the form and send a not working dod data - select('x86_64', from: 'Architecture') - select('rpmmd', from: 'Type') - fill_in('Url', with: '') - click_button('Add Download on Demand') - find(:id, 'flash-messages').must_have_text("Download on Demand can't be created: Validation failed: Url can't be blank") - end - - def test_editing_download_on_demand # spec/features/webui/projects_spec.rb - use_js - - # Login as admin - login_king - visit(project_show_path(project: "home:user5")) - - # Updating via meta - click_link("Advanced") - click_link("Meta") - page.evaluate_script("editors[0].setValue(\"#{PROJECT_WITH_DOWNLOAD_ON_DEMAND.gsub("\n", '\n')}\");") - click_button("Save") - find(:id, 'flash-messages').must_have_text('Config successfully saved!') - - click_link("Repositories") - within(:css, "span.edit-dod-repository-link-container") do - click_link("Edit") - end - - # Fill in the form and send a working dod data - select('i586', from: 'Architecture') - select('deb', from: 'Type') - fill_in('Url', with: 'http://somerandomurl_2.es') - fill_in('Arch. Filter', with: 'i586, noarch') - fill_in('Master Url', with: 'http://somerandomurl__2.es') - fill_in('SSL Fingerprint', with: '33333333444444') - fill_in('Public Key', with: '902RKLJSDFLJF902RKLJSDFLJF902RKLJSDFLJF') - click_button('Update Download on Demand') - find(:id, 'flash-messages').must_have_text('Successfully updated Download on Demand') - page.must_have_link 'http://somerandomurl_2.es' - page.must_have_text 'deb' - - click_link("Repositories") - within(:css, "span.edit-dod-repository-link-container") do - click_link("Edit") - end - - # Fill in the form and send a not working dod data - fill_in('Url', with: '') - click_button('Update Download on Demand') - find(:id, 'flash-messages').must_have_text("Download on Demand can't be updated: Validation failed: Url can't be blank") - page.must_have_link 'http://somerandomurl_2.es' - end - - def test_destroying_download_on_demand # spec/features/webui/projects_spec.rb - use_js - - # Login as admin - login_king - visit(project_show_path(project: "home:user5")) - - # Updating via meta - click_link("Advanced") - click_link("Meta") - page.evaluate_script("editors[0].setValue(\"#{PROJECT_WITH_SEVERAL_DOWNLOAD_ON_DEMAND.gsub("\n", '\n')}\");") - click_button("Save") - find(:id, 'flash-messages').must_have_text('Config successfully saved!') - - click_link("Repositories") - first(:xpath, "//a[text()='Delete']").click - - page.wont_have_text 'Download on demand repositories' - page.wont_have_link 'http://mola.org2' - page.wont_have_text 'rpmmd' - end end diff --git a/src/api/test/functional/webui/package_controller_test.rb b/src/api/test/functional/webui/package_controller_test.rb index f13aebc99558d3150d46641a0de4b6673254c36f..1eddd1e3b01207dba7abd7efbfac43099c77d5fc 100644 --- a/src/api/test/functional/webui/package_controller_test.rb +++ b/src/api/test/functional/webui/package_controller_test.rb @@ -547,4 +547,61 @@ class Webui::PackageControllerTest < Webui::IntegrationTest page.all(:link, 'Trigger Rebuild')[0].click find('#flash-messages').must_have_text('Triggered rebuild for BaseDistro2.0/pack2.linked successfully.') end + + def test_revert_to_revision + use_js + login_king + # create test package + visit project_show_path(project: "BaseDistro2.0") + click_link "Create package" + fill_in 'name', with: 'tst_pack' + click_button "Save changes" + + # add 6 new revision to source package + 6.times { |i| put '/source/BaseDistro2.0/tst_pack/rev_file_test', "revision #{(i + 1)}" } + # check latest revision + visit project_show_path(project: "BaseDistro2.0") + click_link "tst_pack" + click_link "rev_file_test" + page.must_have_text "revision 6" + + # go to revision page and select second last revision (rev5) + visit package_view_revisions_path(project: 'BaseDistro2.0', package: 'tst_pack', meta: '0') + within('div#commit_item_5') do + click_link "Files changed" + end + + # create "revert to revision" submit request + page.must_have_text "Changes of Revision 5" + click_link "Revert BaseDistro2.0 / tst_pack to revision 5" + + # use same project, but set different target package name + page.must_have_text "Create Submit Request" + fill_in 'targetproject', with: 'BaseDistro2.0' + fill_in 'targetpackage', with: 'tst_pack_rev5' + fill_in 'description', with: 'testing revert to revision 5' + click_button 'Ok' + + # check that request was submitted + page.wont_have_selector '.dialog' # wait for the reload + requestid = flash_message.gsub(%r{Created submit request (\d*) to BaseDistro2.0}, '\1').to_i + + # open request from project page and accept it + visit project_show_path(project: "BaseDistro2.0") + click_link "open request" + find("a[href='/request/show/#{requestid}']").click + page.must_have_text "testing revert to revision 5" + page.must_have_text "Submit package BaseDistro2.0 / tst_pack (revision 5) to package BaseDistro2.0 / tst_pack_rev5" + click_button "Accept request" + + # go to reverted package + visit project_show_path(project: "BaseDistro2.0") + click_link "tst_pack_rev5" + page.must_have_text "testing revert to revision 5" + + # verify that correct revision was reverted + click_link "rev_file_test" + page.wont_have_text "revision 6" # from the latest revision + page.must_have_text "revision 5" # from the reverted revision + end end diff --git a/src/api/test/unit/code_quality_test.rb b/src/api/test/unit/code_quality_test.rb index 3e0a62f18fc38de69c6a6d84cadecb94208599bf..25d27ca962afec6179037ebc93844d544869798e 100644 --- a/src/api/test/unit/code_quality_test.rb +++ b/src/api/test/unit/code_quality_test.rb @@ -74,7 +74,7 @@ class CodeQualityTest < ActiveSupport::TestCase 'BsRequestAction#create_expand_package' => 443.16, 'BsRequestAction#default_reviewers' => 141.02, 'BsRequestAction#store_from_xml' => 88.01, - 'BsRequestActionMaintenanceIncident#_merge_pkg_into_maintenance_incident' => 130.81, + 'BsRequestActionMaintenanceIncident#_merge_pkg_into_maintenance_incident' => 153.15, 'BsRequestActionMaintenanceRelease#sanity_check!' => 81.82, 'BsRequestActionSubmit#execute_accept' => 126.42, 'BsRequestPermissionCheck#cmd_changestate_permissions' => 117.09, @@ -98,9 +98,11 @@ class CodeQualityTest < ActiveSupport::TestCase 'User::find_with_credentials' => 131.43, 'UserLdapStrategy::render_grouplist_ldap' => 100.3, 'Webui::DriverUpdateController#save' => 91.69, - 'Webui::PackageController#submit_request' => 95.89, + 'Webui::PackageController#submit_request' => 101.98, 'Webui::PatchinfoController#save' => 240.1, 'Webui::ProjectController#check_devel_package_status' => 81.95, + 'Webui::ProjectController#save_meta' => 83.61, + 'Webui::RequestController#show' => 91.96, 'Webui::SearchController#set_parameters' => 98.04, 'WizardController#package_wizard' => 97.46 } diff --git a/src/api/test/unit/user_test.rb b/src/api/test/unit/user_test.rb index cf4a69d78c17dd7ec1b0d9798bf9dff413fb715a..c5ea03af19f8b96497ad3751fe4b43b7f08c0b42 100644 --- a/src/api/test/unit/user_test.rb +++ b/src/api/test/unit/user_test.rb @@ -8,24 +8,6 @@ class UserTest < ActiveSupport::TestCase @user = User.find_by_login('Iggy') end - def test_login - user = User.authenticate("tom", "buildservice") - assert_equal User.find_by(login: "tom"), user - assert_equal User.find_by(login: "tom"), User.current - - user = User.authenticate("tom", "wrong_pw") - assert_equal nil, user - assert_equal nil, User.current - - user = User.authenticate("nonexistant", "foobar") - assert_equal nil, user - assert_equal nil, User.current - - user = User.authenticate("unconfirmed_user", "thunder") - assert_equal nil, user, "Should not authenticate users with state 'unconfirmed'" - assert_equal nil, User.current - end - def test_create_home_project # spec/models/user_spec.rb User.create(login: 'moises', email: 'moises@home.com', password: '123456') assert Project.find_by(name: 'home:moises') diff --git a/src/backend/BSHTTP.pm b/src/backend/BSHTTP.pm index 54fb0b3b629dd9115aa4120c2ac6ac5b7f7928b7..17bd8be5b1603785861ad0f4440a07320921741f 100644 --- a/src/backend/BSHTTP.pm +++ b/src/backend/BSHTTP.pm @@ -376,6 +376,7 @@ sub cpio_sender { my $r = 0; while(1) { $r = sysread(F, $data, $l > 8192 ? 8192 : $l, length($data)) if $l; + die "Error while reading file $file->{filename}: $!\n" if ! defined($r); $data .= $pad if $r == $l; swrite($sock, $data, $param->{'chunked'}); $data = ''; diff --git a/src/backend/BSSched/BuildJob/KiwiImage.pm b/src/backend/BSSched/BuildJob/KiwiImage.pm index 3f9352685e1744b2930d203d802a9cd9333aa17e..3f4fb3bb843572f8fcfff61bd896a15637d5c400 100644 --- a/src/backend/BSSched/BuildJob/KiwiImage.pm +++ b/src/backend/BSSched/BuildJob/KiwiImage.pm @@ -230,7 +230,7 @@ sub build { no warnings 'redefine'; local *Build::expand = sub { $_[0] = $xp; goto &BSSolv::expander::expand; }; use warnings 'redefine'; - return BSSched::BuildJob::create({ %$ctx, 'conf' => $bconf, 'prpsearchpath' => [], 'pool' => $pool }, $packid, $pdata, $info, [], $edeps, $reason, 0); + return BSSched::BuildJob::create({ %$ctx, 'conf' => $bconf, 'prpsearchpath' => [], 'pool' => $pool, 'realctx' => $ctx }, $packid, $pdata, $info, [], $edeps, $reason, 0); } else { # repo has a configured path, expand kiwi system with it my $prp = "$projid/$repoid"; diff --git a/src/backend/BSSched/BuildJob/Upload.pm b/src/backend/BSSched/BuildJob/Upload.pm index b4b1e00b9f5dda88ced2b02777312f7cfe11efc9..8baac068a8b396b71e01345947f9d855facac873 100644 --- a/src/backend/BSSched/BuildJob/Upload.pm +++ b/src/backend/BSSched/BuildJob/Upload.pm @@ -69,8 +69,10 @@ sub jobfinished { my $gdst = "$gctx->{'reporoot'}/$prp/$myarch"; my $dst = "$gdst/$packid"; mkdir_p($dst); + # find the meta for the successful build my $meta; - $meta = "$jobdatadir/meta" if -e "$jobdatadir/meta"; + $meta = "$jobdatadir/.meta.success" if -e "$jobdatadir/.meta.success"; + $meta = "$jobdatadir/meta" if !$meta && -e "$jobdatadir/meta"; print " - $prp: $packid uploaded\n"; my $useforbuildenabled = 1; $useforbuildenabled = BSUtil::enabled($repoid, $projpacks->{$projid}->{'useforbuild'}, $useforbuildenabled, $myarch); @@ -78,10 +80,19 @@ sub jobfinished { my $prpsearchpath = $gctx->{'prpsearchpath'}->{$prp}; BSSched::BuildResult::update_dst_full($gctx, $prp, $packid, $jobdatadir, $meta, $useforbuildenabled, $prpsearchpath); $changed->{$prp} = 2 if $useforbuildenabled; - if ($meta) { + if (-e "$jobdatadir/.logfile.success") { + mkdir_p("$gdst/:logfiles.success"); + rename("$jobdatadir/.logfile.success", "$gdst/:logfiles.success/$packid"); + } + if (-e "$jobdatadir/.logfile.fail") { + mkdir_p("$gdst/:logfiles.fail"); + rename("$jobdatadir/.logfile.fail", "$gdst/:logfiles.fail/$packid"); + } + if (-e "$jobdatadir/meta") { mkdir_p("$gdst/:meta"); - rename($meta, "$gdst/:meta/$packid"); + rename("$jobdatadir/meta", "$gdst/:meta/$packid"); } + rename("$jobdatadir/logfile", "$dst/logfile") if -e "$jobdatadir/logfile"; my $repounchanged = $gctx->{'repounchanged'}; delete $repounchanged->{$prp} if $useforbuildenabled; $repounchanged->{$prp} = 2 if $repounchanged->{$prp}; diff --git a/src/backend/BSSched/BuildResult.pm b/src/backend/BSSched/BuildResult.pm index 80aaf0a27553555cdca8c99a959477e21420e9e0..b2cafc20e9a1cef5966f4a09e22571c3963e53b9 100644 --- a/src/backend/BSSched/BuildResult.pm +++ b/src/backend/BSSched/BuildResult.pm @@ -324,7 +324,7 @@ sub update_dst_full { my $jobbininfo; if (defined($jobdir)) { @jobfiles = sort(ls($jobdir)); - @jobfiles = grep {$_ ne 'history' && $_ ne 'logfile' && $_ ne 'meta' && $_ ne 'status' && $_ ne 'reason' && $_ ne '.bininfo'} @jobfiles; + @jobfiles = grep {$_ ne 'history' && $_ ne 'logfile' && $_ ne 'meta' && $_ ne 'status' && $_ ne 'reason' && $_ ne '.bininfo' && $_ ne '.meta.success' && $_ ne '.logfile.success' && $_ ne '.logfile.fail'} @jobfiles; $jobbininfo = BSUtil::retrieve("$jobdir/.bininfo", 1); if ($jobbininfo && !($jobdir eq $dst) && !$jobbininfo->{'.bininfo'}) { # old style jobdir bininfo, ignore diff --git a/src/backend/BSSched/DoD.pm b/src/backend/BSSched/DoD.pm index 1ac4d1860a76017514852c465dc3523a8de736f0..7130de5050b9ccdd336a0fe7d9515cb90065e0b6 100644 --- a/src/backend/BSSched/DoD.pm +++ b/src/backend/BSSched/DoD.pm @@ -128,6 +128,7 @@ sub clean_obsolete_dodpackages { sub dodcheck { my ($ctx, $pool, $arch, @pkgs) = @_; + $ctx = $ctx->{'realctx'} if $ctx->{'realctx'}; # we need the real one to add entries my %names; if (defined &BSSolv::repo::dodcookie) { %names = (%names, $_->pkgnames()) for grep {$_->dodurl() || $_->dodcookie()} $pool->repos(); diff --git a/src/backend/BSXML.pm b/src/backend/BSXML.pm index 958ba52ddf4d8675b7a228917d140b63cdde9b59..f9d296b500dced101748366b7a1b64215bd1acde 100644 --- a/src/backend/BSXML.pm +++ b/src/backend/BSXML.pm @@ -140,6 +140,7 @@ our $proj = [ [], 'title', 'description', + 'url', [[ 'link' => 'project', ]], @@ -730,6 +731,7 @@ our $worker = [ [ 'flag' ], ], 'processors', + 'jobs', # compat for OBS 2.8 worker 'memory', # in MBytes 'swap', # in MBytes 'disk', # in MBytes diff --git a/src/backend/bs_publish b/src/backend/bs_publish index 65bb56a01f953650d97616cfe73357de200e8ce6..77a06f1e31cf8db7177d0fd4163a01777fb46d11 100755 --- a/src/backend/bs_publish +++ b/src/backend/bs_publish @@ -808,7 +808,7 @@ sub createrepo_staticlinks { # kiwi appliance $link = "$1$3"; $link = "$1-$2$3" if $versioned; - } elsif (/^(.*)-(\d+\.\d+\.\d+)?(\.\w+)?-Build\d+\.\d+(\.(raw.install.raw.xz|raw.xz|box|json|install.iso|tbz|tgz|vmx|vmdk|vhdfixed.xz|iso|qcow2|qcow2.xz|ova)?(?:\.sha256)?)$/s) { + } elsif (/^(.*)-(\d+\.\d+\.\d+)?(\.\w+)?-Build\d+\.\d+(\.(raw.install.raw.xz|raw.xz|box|json|install.iso|tbz|tgz|vmx|vmdk|vdi|vhdfixed.xz|iso|qcow2|qcow2.xz|ova)?(?:\.sha256)?)$/s) { # kiwi appliance my $profile = $3 || ""; $link = "$1$profile$4"; @@ -1477,7 +1477,7 @@ sub publish { $p = "$bin"; } elsif ($bin =~ /\.dsc(?:\.sha256)?$/) { $p = "$bin"; - } elsif ($bin =~ /\.(?:box|json|ovf|qcow2|qcow2\.xz|vhdfixed.xz|vmx|vmdk)(?:\.sha256)?$/) { + } elsif ($bin =~ /\.(?:box|json|ovf|qcow2|qcow2\.xz|vdi|vhdfixed.xz|vmx|vmdk)(?:\.sha256)?$/) { $p = "$bin"; } elsif ($bin =~ /^(.*)\.packages$/) { $p = "$bin"; @@ -2111,6 +2111,23 @@ publishprog_done: } } + # support for regex usage in $BSConfig::unpublishedhook + my $unpublish_prp = $prp; + if ($BSConfig::unpublishedhook_use_regex || $BSConfig::unpublishedhook_use_regex) { + for my $key (sort {$b cmp $a} keys %{$BSConfig::unpublishedhook}) { + if ($prp =~ /^$key/) { + $unpublish_prp = $key; + last; + } + } + } + if ($BSConfig::unpublishedhook && $BSConfig::unpublishedhook->{$unpublish_prp}) { + my $hook = $BSConfig::unpublishedhook->{$unpublish_prp}; + $hook = [ $hook ] unless ref $hook; + print " calling unpublished hook @$hook\n"; + qsystem(@$hook, $prp, $extrep, @db_deleted) && warn(" @$hook failed: $?\n"); + } + # support for regex usage in $BSConfig::publishedhook my $publish_prp = $prp; if ($BSConfig::publishedhook_use_regex || $BSConfig::publishedhook_use_regex) { diff --git a/src/backend/bs_repserver b/src/backend/bs_repserver index 6c52647a976fd92f1ffef8d08fa2b5c1e4ea38ea..e8de797b219502cd30aed4ec3c9f98ba20945405 100755 --- a/src/backend/bs_repserver +++ b/src/backend/bs_repserver @@ -2057,7 +2057,8 @@ sub copybuild { die("job lock failed\n"); } my $dir = "$jobsdir/$arch/$job:dir"; - my $odir = "$reporoot/$oprojid/$orepoid/$arch/$opackid"; + my $ogdst = "$reporoot/$oprojid/$orepoid/$arch"; + my $odir = "$ogdst/$opackid"; mkdir_p($dir); my %delayed_linking; my $needsign; @@ -2112,7 +2113,11 @@ sub copybuild { } } } - link("$odir/.meta.success", "$dir/meta") if -e "$odir/.meta.success"; + link("$odir/.meta.success", "$dir/.meta.success") if -e "$odir/.meta.success"; + link("$ogdst/:meta/$opackid", "$dir/meta") if -e "$ogdst/:meta/$opackid"; + link("$ogdst/:logfiles.success/$opackid", "$dir/.logfile.success"); + link("$ogdst/:logfiles.fail/$opackid", "$dir/.logfile.fail"); + BSUtil::touch("$dir/.preinstallimage") if -e "$odir/.preinstallimage"; # we run the linking of directory trees in background, since it can take a long time # for simple files it happened already