1# frozen_string_literal: true 2 3# Gitlab::VisibilityLevel module 4# 5# Define allowed public modes that can be used for 6# GitLab projects to determine project public mode 7# 8module Gitlab 9 module VisibilityLevel 10 extend ActiveSupport::Concern 11 12 included do 13 scope :public_only, -> { where(visibility_level: PUBLIC) } 14 scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) } 15 scope :private_only, -> { where(visibility_level: PRIVATE) } 16 scope :non_public_only, -> { where.not(visibility_level: PUBLIC) } 17 18 scope :public_to_user, -> (user = nil) do 19 where(visibility_level: VisibilityLevel.levels_for_user(user)) 20 end 21 end 22 23 PRIVATE = 0 unless const_defined?(:PRIVATE) 24 INTERNAL = 10 unless const_defined?(:INTERNAL) 25 PUBLIC = 20 unless const_defined?(:PUBLIC) 26 27 class << self 28 delegate :values, to: :options 29 30 def levels_for_user(user = nil) 31 return [PUBLIC] unless user 32 33 if user.can_read_all_resources? 34 [PRIVATE, INTERNAL, PUBLIC] 35 elsif user.external? 36 [PUBLIC] 37 else 38 [INTERNAL, PUBLIC] 39 end 40 end 41 42 def string_values 43 string_options.keys 44 end 45 46 def options 47 { 48 s_('VisibilityLevel|Private') => PRIVATE, 49 s_('VisibilityLevel|Internal') => INTERNAL, 50 s_('VisibilityLevel|Public') => PUBLIC 51 } 52 end 53 54 def string_options 55 { 56 'private' => PRIVATE, 57 'internal' => INTERNAL, 58 'public' => PUBLIC 59 } 60 end 61 62 def allowed_levels 63 restricted_levels = Gitlab::CurrentSettings.restricted_visibility_levels 64 65 self.values - Array(restricted_levels) 66 end 67 68 def closest_allowed_level(target_level) 69 highest_allowed_level = allowed_levels.select { |level| level <= target_level }.max 70 71 # If all levels are restricted, fall back to PRIVATE 72 highest_allowed_level || PRIVATE 73 end 74 75 def allowed_for?(user, level) 76 user.admin? || allowed_level?(level.to_i) 77 end 78 79 # Level should be a numeric value, e.g. `20` 80 # Return true if the specified level is allowed for the current user. 81 def allowed_level?(level) 82 valid_level?(level) && non_restricted_level?(level) 83 end 84 85 def non_restricted_level?(level) 86 !restricted_level?(level) 87 end 88 89 def restricted_level?(level) 90 restricted_levels = Gitlab::CurrentSettings.restricted_visibility_levels 91 92 if restricted_levels.nil? 93 false 94 else 95 restricted_levels.include?(level) 96 end 97 end 98 99 def public_visibility_restricted? 100 restricted_level?(PUBLIC) 101 end 102 103 def valid_level?(level) 104 options.value?(level) 105 end 106 107 def level_name(level) 108 options.key(level.to_i) || s_('VisibilityLevel|Unknown') 109 end 110 111 def level_value(level) 112 return level.to_i if level.to_i.to_s == level.to_s && string_options.key(level.to_i) 113 114 string_options[level] || PRIVATE 115 end 116 117 def string_level(level) 118 string_options.key(level) 119 end 120 end 121 122 def visibility_level_previous_changes 123 previous_changes[:visibility_level] 124 end 125 126 def private? 127 visibility_level_value == PRIVATE 128 end 129 130 def internal? 131 visibility_level_value == INTERNAL 132 end 133 134 def public? 135 visibility_level_value == PUBLIC 136 end 137 138 def visibility_level_value 139 self[visibility_level_field] 140 end 141 142 def visibility 143 Gitlab::VisibilityLevel.string_level(visibility_level_value) 144 end 145 146 def visibility=(level) 147 self[visibility_level_field] = Gitlab::VisibilityLevel.level_value(level) 148 end 149 150 def visibility_attribute_present?(attributes) 151 visibility_level_attributes.each do |attr| 152 return true if attributes[attr].present? 153 end 154 155 false 156 end 157 158 def visibility_attribute_value(attributes) 159 visibility_level_attributes.each do |attr| 160 return attributes[attr] if attributes.has_key?(attr) 161 end 162 163 nil 164 end 165 166 def visibility_level_attributes 167 [visibility_level_field, visibility_level_field.to_s, 168 :visibility, 'visibility'] 169 end 170 end 171end 172