# frozen_string_literal: true module License module Management module Report class V1 < Base def to_h { licenses: license_summary, dependencies: formatted_dependencies(dependencies) } end private # when a dependency has multiple licenses, this will join the licenses into a single name # this defect was backported from the [html2json](https://gitlab.com/gitlab-org/security-products/license-management/blob/7f175952a5a047d785b5ea72c15a10642523c62a/html2json.js) version of this script. def license_summary dependencies .map { |dependency| join_license_names(dependency.licenses) } .flatten .group_by { |name| name } .map { |license, items| { count: items.count, name: license } } .sort_by { |hash| [-hash[:count], hash[:name]] } end # when a dependency has more than one license # this method chooses one of the urls. # to maintain backwards compatibility this bug has been carried forward. def license_for(dependency) license = { name: join_license_names(dependency.licenses) } urls = dependency.licenses.map(&:url).reject { |x| blank?(x) }.uniq.sort logger.info("multiple urls detected: #{urls.inspect}") if urls.size > 1 url = urls[0] || license_data(dependency.licenses.first)['url'] license[:url] = url if present?(url) license end def join_license_names(licenses) licenses.map { |x| best_name_for(x) }.sort.reverse.join(', ') end def map_from_dependency(dependency) result = { license: license_for(dependency), dependency: { name: dependency.name, url: dependency.homepage, description: description_for(dependency), pathes: paths_from(dependency) } } result[:dependency].delete(:url) if blank?(dependency.homepage) result end def formatted_dependencies(dependencies) dependencies.map { |x| map_from_dependency(x) } end def best_name_for(license) license_data(license)['name'] end def license_data(license) { 'name' => license.name.split(/[\r\n]+/)[0], 'url' => license.url || '' } end end end end end