Commit 5686de1e authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Refactor code related to maven packages

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent e4164106
...@@ -1923,9 +1923,10 @@ ActiveRecord::Schema.define(version: 20180807153545) do ...@@ -1923,9 +1923,10 @@ ActiveRecord::Schema.define(version: 20180807153545) do
create_table "packages_maven_metadata", force: :cascade do |t| create_table "packages_maven_metadata", force: :cascade do |t|
t.integer "package_id", null: false t.integer "package_id", null: false
t.string "path", null: false
t.string "app_group", null: false t.string "app_group", null: false
t.string "app_name", null: false t.string "app_name", null: false
t.string "app_version", null: false t.string "app_version"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
...@@ -1949,7 +1950,7 @@ ActiveRecord::Schema.define(version: 20180807153545) do ...@@ -1949,7 +1950,7 @@ ActiveRecord::Schema.define(version: 20180807153545) do
create_table "packages_packages", force: :cascade do |t| create_table "packages_packages", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.string "name" t.string "name", null: false
t.string "version" t.string "version"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
......
class Packages::MavenPackageFinder
attr_reader :project, :path
def initialize(project, path)
@project = project
@path = path
end
def execute
packages.last
end
def execute!
packages.last!
end
private
def packages
project.packages.joins(:maven_metadatum)
.where(packages_maven_metadata: { path: path })
end
end
...@@ -2,24 +2,22 @@ ...@@ -2,24 +2,22 @@
module Packages module Packages
class CreateMavenPackageService < BaseService class CreateMavenPackageService < BaseService
def execute def execute
package = Packages::Package.create!( package = project.packages.create!(
project: project, name: params[:name],
name: full_app_name, version: params[:version]
version: params[:app_version]
) )
Packages::MavenMetadatum.create!( app_group, _, app_name = params[:name].rpartition('/')
package: package, app_group.tr!('/', '.')
app_group: params[:app_group],
app_name: params[:app_name],
app_version: params[:app_version]
)
end
private package.create_maven_metadatum!(
path: params[:path],
app_group: app_group,
app_name: app_name,
app_version: params[:version]
)
def full_app_name package
params[:app_group] + '/' + params[:app_name]
end end
end end
end end
class Packages::CreatePackageFileService
attr_reader :package, :params
def initialize(package, params)
@package = package
@params = params
end
def execute
package.package_files.create!(
file: parmas[:file],
size: params[:size],
file_name: params[:file_name],
file_type: params[:file_type],
file_sha1: params[:file_sha1],
file_md5: params[:file_md5]
)
end
end
...@@ -5,7 +5,7 @@ class CreatePackagesPackages < ActiveRecord::Migration ...@@ -5,7 +5,7 @@ class CreatePackagesPackages < ActiveRecord::Migration
def change def change
create_table :packages_packages do |t| create_table :packages_packages do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
t.string :name t.string :name, null: false
t.string :version t.string :version
t.timestamps_with_timezone null: false t.timestamps_with_timezone null: false
......
...@@ -9,9 +9,10 @@ class CreatePackagesMavenMetadata < ActiveRecord::Migration ...@@ -9,9 +9,10 @@ class CreatePackagesMavenMetadata < ActiveRecord::Migration
def up def up
create_table :packages_maven_metadata do |t| create_table :packages_maven_metadata do |t|
t.references :package, index: true, null: false t.references :package, index: true, null: false
t.string :path, null: false
t.string :app_group, null: false t.string :app_group, null: false
t.string :app_name, null: false t.string :app_name, null: false
t.string :app_version, null: false t.string :app_version
t.timestamps_with_timezone null: false t.timestamps_with_timezone null: false
end end
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
module API module API
class MavenPackages < Grape::API class MavenPackages < Grape::API
MAVEN_ENDPOINT_REQUIREMENTS = { MAVEN_ENDPOINT_REQUIREMENTS = {
app_name: API::NO_SLASH_URL_PART_REGEX,
app_version: API::NO_SLASH_URL_PART_REGEX,
file_name: API::NO_SLASH_URL_PART_REGEX file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze }.freeze
...@@ -25,14 +23,6 @@ module API ...@@ -25,14 +23,6 @@ module API
[file_name, nil] [file_name, nil]
end end
end end
def valid_metadata_xml?(xml)
version = Nokogiri::XML(xml).css('metadata:root > version').text
# Skip handling top level maven-metadata.xml (one without the version) for now.
# Also make sure version in the metadata file is equal to one in the URL
version.present? && version == params[:app_version]
end
end end
params do params do
...@@ -43,21 +33,18 @@ module API ...@@ -43,21 +33,18 @@ module API
detail 'This feature was introduced in GitLab 11.3' detail 'This feature was introduced in GitLab 11.3'
end end
params do params do
requires :app_group, type: String, desc: 'Package group id' requires :path, type: String, desc: 'Package path'
requires :app_name, type: String, desc: 'Package artifact id'
requires :app_version, type: String, desc: 'Package version'
requires :file_name, type: String, desc: 'Package file name' requires :file_name, type: String, desc: 'Package file name'
end end
get ':id/packages/maven/*app_group/:app_name/:app_version/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do get ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
unauthorized! unless can?(current_user, :read_package, user_project) unauthorized! unless can?(current_user, :read_package, user_project)
file_name, format = extract_format(params[:file_name]) file_name, format = extract_format(params[:file_name])
metadata = ::Packages::MavenMetadatum.find_by!(app_group: params[:app_group], package = ::Packages::MavenPackageFinder
app_name: params[:app_name], .new(user_project, params[:path]).execute!
app_version: params[:app_version])
package_file = metadata.package.package_files.recent.find_by!(file_name: file_name) package_file = package.package_files.recent.find_by!(file_name: file_name)
case format case format
when 'md5' when 'md5'
...@@ -73,12 +60,10 @@ module API ...@@ -73,12 +60,10 @@ module API
detail 'This feature was introduced in GitLab 11.3' detail 'This feature was introduced in GitLab 11.3'
end end
params do params do
requires :app_group, type: String, desc: 'Package group id' requires :path, type: String, desc: 'Package path'
requires :app_name, type: String, desc: 'Package artifact id'
requires :app_version, type: String, desc: 'Package version'
requires :file_name, type: String, desc: 'Package file name' requires :file_name, type: String, desc: 'Package file name'
end end
put ':id/packages/maven/*app_group/:app_name/:app_version/:file_name/authorize', requirements: MAVEN_ENDPOINT_REQUIREMENTS do put ':id/packages/maven/*path/:file_name/authorize', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
not_allowed! unless Gitlab.config.packages.enabled not_allowed! unless Gitlab.config.packages.enabled
unauthorized! unless can?(current_user, :admin_package, user_project) unauthorized! unless can?(current_user, :admin_package, user_project)
...@@ -94,17 +79,17 @@ module API ...@@ -94,17 +79,17 @@ module API
detail 'This feature was introduced in GitLab 11.3' detail 'This feature was introduced in GitLab 11.3'
end end
params do params do
requires :app_group, type: String, desc: 'Package group id' requires :path, type: String, desc: 'Package path'
requires :app_name, type: String, desc: 'Package artifact id'
requires :app_version, type: String, desc: 'Package version'
requires :file_name, type: String, desc: 'Package file name' requires :file_name, type: String, desc: 'Package file name'
optional 'file.path', type: String, desc: %q(path to locally stored body (generated by Workhorse)) optional 'file.path', type: String, desc: %q(path to locally stored body (generated by Workhorse))
optional 'file.name', type: String, desc: %q(real filename as send in Content-Disposition (generated by Workhorse)) optional 'file.name', type: String, desc: %q(real filename as send in Content-Disposition (generated by Workhorse))
optional 'file.type', type: String, desc: %q(real content type as send in Content-Type (generated by Workhorse)) optional 'file.type', type: String, desc: %q(real content type as send in Content-Type (generated by Workhorse))
optional 'file.size', type: Integer, desc: %q(real size of file (generated by Workhorse)) optional 'file.size', type: Integer, desc: %q(real size of file (generated by Workhorse))
optional 'file.md5', type: String, desc: %q(md5 checksum of the file (generated by Workhorse))
optional 'file.sha1', type: String, desc: %q(sha1 checksum of the file (generated by Workhorse))
optional 'file.sha256', type: String, desc: %q(sha256 checksum of the file (generated by Workhorse)) optional 'file.sha256', type: String, desc: %q(sha256 checksum of the file (generated by Workhorse))
end end
put ':id/packages/maven/*app_group/:app_name/:app_version/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do put ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
not_allowed! unless Gitlab.config.packages.enabled not_allowed! unless Gitlab.config.packages.enabled
unauthorized! unless can?(current_user, :admin_package, user_project) unauthorized! unless can?(current_user, :admin_package, user_project)
...@@ -115,46 +100,48 @@ module API ...@@ -115,46 +100,48 @@ module API
uploaded_file = UploadedFile.from_params(params, :file, ::Packages::PackageFileUploader.workhorse_local_upload_path) uploaded_file = UploadedFile.from_params(params, :file, ::Packages::PackageFileUploader.workhorse_local_upload_path)
bad_request!('Missing package file!') unless uploaded_file bad_request!('Missing package file!') unless uploaded_file
metadata = ::Packages::MavenMetadatum.find_by(app_group: params[:app_group], package = ::Packages::MavenPackageFinder
app_name: params[:app_name], .new(user_project, params[:path]).execute
app_version: params[:app_version])
# TODO: Refactor. We don't need to read file for every request, only metadata and md5/sha1
string_file = File.read(uploaded_file)
unless metadata unless package
if file_name == MAVEN_METADATA_FILE if file_name == MAVEN_METADATA_FILE
return unless valid_metadata_xml?(string_file) # Maven uploads several files during `mvn deploy` in next order:
# - my-company/my-app/1.0-SNAPSHOT/my-app.jar
# - my-company/my-app/1.0-SNAPSHOT/my-app.pom
# - my-company/my-app/1.0-SNAPSHOT/maven-metadata.xml
# - my-company/my-app/maven-metadata.xml
#
# The last xml file does not have VERSION in URL because it contains
# information about all versions.
package_name, version = params[:path], nil
else
package_name, _, version = params[:path].rpartition('/')
end end
# There is no metadata for this upload. We need to create a package package_params = {
# record and corresponding maven metadata record name: package_name,
metadata = Packages::CreateMavenPackageService.new(user_project, current_user, params).execute path: params[:path],
version: version
}
package = ::Packages::CreateMavenPackageService.new(user_project, current_user, package_params).execute
end end
if format if format
# Maven tries to create a md5 and sha1 files for each package file. # TODO: Validate our checksum with Maven.
# Instead, we update existing package file record with such data. no_content!
package_file = metadata.package.package_files.recent.find_by!(file_name: file_name)
case format
when 'md5'
package_file.file_md5 = string_file
when 'sha1'
package_file.file_sha1 = string_file
end
else else
# TODO: If maven-metadata.xml file is present for this package, we file_params = {
# need to update it instead of creating a new one file: uploaded_file,
package_file = metadata.package.package_files.new size: params['file.size'],
package_file.file_name = file_name file_name: file_name,
package_file.file_type = file_name.rpartition('.').last file_type: params['file.type'],
file_sha1: params['file.sha1'],
# Convert string into CarrierWave compatible StringIO object file_md5: params['file.md5']
package_file.file = uploaded_file }
::Packages::CreatePackageFileService.new(package, file_params).execute
end end
package_file.save!
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment