Class: Packages::Protection::Rule
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Packages::Protection::Rule
- Defined in:
- app/models/packages/protection/rule.rb
Constant Summary collapse
- NPM_PACKAGE_NAME_FORMAT =
{ with: Gitlab::Regex::Packages::Protection::Rules.protection_rules_npm_package_name_pattern_regex, message: ->(_object, _data) { _('should be a valid NPM package name with optional wildcard characters.') } }.freeze
- PYPI_PACKAGE_NAME_FORMAT =
{ with: Gitlab::Regex::Packages::Protection::Rules.protection_rules_pypi_package_name_pattern_regex, message: ->(_object, _data) { _('should be a valid PyPI package name with optional wildcard characters.') } }.freeze
Constants inherited from ApplicationRecord
Constants included from HasCheckConstraints
HasCheckConstraints::NOT_NULL_CHECK_PATTERN
Constants included from ResetOnColumnErrors
ResetOnColumnErrors::MAX_RESET_PERIOD
Class Method Summary collapse
- .for_action_exists?(action:, access_level:, package_name:, package_type:) ⇒ Boolean
- .for_delete_exists?(access_level:, package_name:, package_type:) ⇒ Boolean
-
.for_push_exists_for_projects_and_packages(projects_and_packages) ⇒ ActiveRecord::Result
Accepts a list of projects and packages and returns a result set indicating whether the package name is protected.
Instance Method Summary collapse
- #at_least_one_minimum_access_level_must_be_present ⇒ Object
- #ensure_pattern_type_and_target_field ⇒ Object
Methods inherited from ApplicationRecord
===, cached_column_list, #create_or_load_association, current_transaction, declarative_enum, default_select_columns, delete_all_returning, #deleted_from_database?, id_in, id_not_in, iid_in, nullable_column?, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order
Methods included from Organizations::Sharding
Methods included from ResetOnColumnErrors
#reset_on_union_error, #reset_on_unknown_attribute_error
Methods included from Gitlab::SensitiveSerializableHash
Class Method Details
.for_action_exists?(action:, access_level:, package_name:, package_type:) ⇒ Boolean
63 64 65 66 67 68 69 70 71 72 |
# File 'app/models/packages/protection/rule.rb', line 63 def self.for_action_exists?(action:, access_level:, package_name:, package_type:) return false if [access_level, package_name, package_type].any?(&:blank?) minimum_access_level_column = "minimum_access_level_for_#{action}" for_package_type(package_type) .where(":access_level < #{minimum_access_level_column}", access_level: access_level) .for_package_name(package_name) .exists? end |
.for_delete_exists?(access_level:, package_name:, package_type:) ⇒ Boolean
58 59 60 61 |
# File 'app/models/packages/protection/rule.rb', line 58 def self.for_delete_exists?(access_level:, package_name:, package_type:) for_action_exists?(action: :delete, access_level: access_level, package_name: package_name, package_type: package_type) end |
.for_push_exists_for_projects_and_packages(projects_and_packages) ⇒ ActiveRecord::Result
Accepts a list of projects and packages and returns a result set indicating whether the package name is protected.
the project id (bigint), the package name (string) and the package type (smallint). is protected.
Example:
Packages::Protection::Rule.for_push_exists_for_projects_and_packages([
[1, '@my_group/my_project_1/package_1', 2],
[1, '@my_group/my_project_1/package_2', 2],
[2, '@my_group/my_project_2/package_1', 3],
...
])
[
{'project_id' => 1, 'package_name' => '@my_group/my_project_1/package_1', 'package_type' => 2,
'protected' => true},
{'project_id' => 1, 'package_name' => '@my_group/my_project_1/package_2', 'package_type' => 2,
'protected' => false},
{'project_id' => 2, 'package_name' => '@my_group/my_project_2/package_1', 'package_type' => 3,
'protected' => true},
...
]
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'app/models/packages/protection/rule.rb', line 101 def self.for_push_exists_for_projects_and_packages(projects_and_packages) return none if projects_and_packages.blank? project_ids, package_names, package_types = projects_and_packages.transpose cte_query_sql = <<~SQL unnest( ARRAY[:project_ids]::bigint[], ARRAY[:package_names]::text[], ARRAY[:package_types]::smallint[] ) AS projects_and_packages(project_id, package_name, package_type) SQL cte_query = select('*').from(sanitize_sql_array( [cte_query_sql, { project_ids: project_ids, package_names: package_names, package_types: package_types }] )) cte_name = :projects_and_packages_cte cte = Gitlab::SQL::CTE.new(cte_name, cte_query) rules_cte_project_id = "#{cte_name}.#{adapter_class.quote_column_name('project_id')}" rules_cte_package_name = "#{cte_name}.#{adapter_class.quote_column_name('package_name')}" rules_cte_package_type = "#{cte_name}.#{adapter_class.quote_column_name('package_type')}" protection_rule_exsits_subquery = select(1) .where("#{rules_cte_project_id} = project_id") .where(arel_table[:package_type].eq(Arel.sql(rules_cte_package_type))) .where("#{rules_cte_package_name} ILIKE #{::Gitlab::SQL::Glob.to_like('package_name_pattern')}") query = select( rules_cte_project_id, rules_cte_package_type, rules_cte_package_name, sanitize_sql_array(['EXISTS(?) AS protected', protection_rule_exsits_subquery]) ).from(Arel.sql(cte_name.to_s)) connection.exec_query(query.with(cte.to_arel).to_sql) end |
Instance Method Details
#at_least_one_minimum_access_level_must_be_present ⇒ Object
141 142 143 144 145 |
# File 'app/models/packages/protection/rule.rb', line 141 def at_least_one_minimum_access_level_must_be_present return unless minimum_access_level_for_delete.blank? && minimum_access_level_for_push.blank? errors.add(:base, _('A rule must have at least a minimum access role for push or delete.')) end |
#ensure_pattern_type_and_target_field ⇒ Object
147 148 149 150 |
# File 'app/models/packages/protection/rule.rb', line 147 def ensure_pattern_type_and_target_field self.pattern_type ||= Packages::Protection::Rule.pattern_types[:wildcard] self.target_field ||= Packages::Protection::Rule.target_fields[:package_name] end |