1# frozen_string_literal: true 2 3require 'spec_helper' 4 5RSpec.describe IssuePolicy do 6 include ExternalAuthorizationServiceHelpers 7 8 let(:guest) { create(:user) } 9 let(:author) { create(:user) } 10 let(:assignee) { create(:user) } 11 let(:reporter) { create(:user) } 12 let(:group) { create(:group, :public) } 13 let(:reporter_from_group_link) { create(:user) } 14 let(:non_member) { create(:user) } 15 let(:support_bot) { User.support_bot } 16 17 def permissions(user, issue) 18 described_class.new(user, issue) 19 end 20 21 shared_examples 'support bot with service desk enabled' do 22 before do 23 allow(::Gitlab::IncomingEmail).to receive(:enabled?) { true } 24 allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true } 25 26 project.update!(service_desk_enabled: true) 27 end 28 29 it 'allows support_bot to read issues, create and set metadata on new issues' do 30 expect(permissions(support_bot, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 31 expect(permissions(support_bot, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 32 expect(permissions(support_bot, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 33 end 34 end 35 36 shared_examples 'support bot with service desk disabled' do 37 it 'does not allow support_bot to read issues, create and set metadata on new issues' do 38 expect(permissions(support_bot, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 39 expect(permissions(support_bot, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 40 expect(permissions(support_bot, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality) 41 end 42 end 43 44 context 'a private project' do 45 let(:project) { create(:project, :private) } 46 let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) } 47 let(:issue_no_assignee) { create(:issue, project: project) } 48 let(:new_issue) { build(:issue, project: project, assignees: [assignee], author: author) } 49 50 before do 51 project.add_guest(guest) 52 project.add_guest(author) 53 project.add_guest(assignee) 54 project.add_reporter(reporter) 55 56 group.add_reporter(reporter_from_group_link) 57 58 create(:project_group_link, group: group, project: project) 59 end 60 61 it 'allows guests to read issues' do 62 expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid) 63 expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 64 65 expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 66 expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 67 68 expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 69 end 70 71 it 'allows reporters to read, update, and admin issues' do 72 expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 73 expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 74 expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 75 end 76 77 it 'allows reporters from group links to read, update, and admin issues' do 78 expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 79 expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 80 expect(permissions(reporter_from_group_link, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 81 end 82 83 it 'allows issue authors to read and update their issues' do 84 expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 85 expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 86 87 expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 88 expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 89 90 expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 91 end 92 93 it 'allows issue assignees to read and update their issues' do 94 expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 95 expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 96 97 expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 98 expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 99 100 expect(permissions(assignee, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 101 end 102 103 it 'does not allow non-members to read, update or create issues' do 104 expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 105 expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 106 expect(permissions(non_member, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality) 107 end 108 109 it_behaves_like 'support bot with service desk disabled' 110 it_behaves_like 'support bot with service desk enabled' 111 112 context 'with confidential issues' do 113 let(:confidential_issue) { create(:issue, :confidential, project: project, assignees: [assignee], author: author) } 114 let(:confidential_issue_no_assignee) { create(:issue, :confidential, project: project) } 115 116 it 'does not allow non-members to read confidential issues' do 117 expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 118 expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 119 end 120 121 it 'does not allow guests to read confidential issues' do 122 expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 123 expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 124 end 125 126 it 'allows reporters to read, update, and admin confidential issues' do 127 expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 128 expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 129 end 130 131 it 'allows reporters from group links to read, update, and admin confidential issues' do 132 expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 133 expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 134 end 135 136 it 'allows issue authors to read and update their confidential issues' do 137 expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 138 expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 139 140 expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 141 expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 142 end 143 144 it 'does not allow issue author to read or update confidential issue moved to an private project' do 145 confidential_issue.project = create(:project, :private) 146 147 expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality) 148 end 149 150 it 'allows issue assignees to read and update their confidential issues' do 151 expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 152 expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 153 154 expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 155 end 156 157 it 'does not allow issue assignees to read or update confidential issue moved to an private project' do 158 confidential_issue.project = create(:project, :private) 159 160 expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata, :set_confidentiality) 161 end 162 end 163 end 164 165 context 'a public project' do 166 let(:project) { create(:project, :public) } 167 let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) } 168 let(:issue_no_assignee) { create(:issue, project: project) } 169 let(:issue_locked) { create(:issue, :locked, project: project, author: author, assignees: [assignee]) } 170 let(:new_issue) { build(:issue, project: project) } 171 172 before do 173 project.add_guest(guest) 174 project.add_reporter(reporter) 175 176 group.add_reporter(reporter_from_group_link) 177 178 create(:project_group_link, group: group, project: project) 179 end 180 181 it 'does not allow anonymous user to create todos' do 182 expect(permissions(nil, issue)).to be_allowed(:read_issue) 183 expect(permissions(nil, issue)).to be_disallowed(:create_todo, :update_subscription, :set_issue_metadata, :set_confidentiality) 184 expect(permissions(nil, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality) 185 end 186 187 it 'allows guests to read issues' do 188 expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo, :update_subscription) 189 expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 190 191 expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 192 expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 193 194 expect(permissions(guest, issue_locked)).to be_allowed(:read_issue, :read_issue_iid) 195 expect(permissions(guest, issue_locked)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 196 197 expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 198 end 199 200 it 'allows reporters to read, update, reopen, and admin issues' do 201 expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 202 expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 203 expect(permissions(reporter, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 204 expect(permissions(reporter, issue_locked)).to be_disallowed(:reopen_issue) 205 expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 206 end 207 208 it 'allows reporters from group links to read, update, reopen and admin issues' do 209 expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 210 expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 211 expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 212 expect(permissions(reporter_from_group_link, issue_locked)).to be_disallowed(:reopen_issue) 213 expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality) 214 end 215 216 it 'allows issue authors to read, reopen and update their issues' do 217 expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue) 218 expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 219 220 expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 221 expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 222 223 expect(permissions(author, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 224 expect(permissions(author, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 225 226 expect(permissions(author, new_issue)).to be_allowed(:create_issue) 227 expect(permissions(author, new_issue)).to be_disallowed(:set_issue_metadata) 228 end 229 230 it 'allows issue assignees to read, reopen and update their issues' do 231 expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue) 232 expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 233 234 expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 235 expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 236 237 expect(permissions(assignee, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 238 expect(permissions(assignee, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality) 239 end 240 241 it 'allows non-members to read and create issues' do 242 expect(permissions(non_member, issue)).to be_allowed(:read_issue, :read_issue_iid) 243 expect(permissions(non_member, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 244 expect(permissions(non_member, new_issue)).to be_allowed(:create_issue) 245 end 246 247 it 'allows non-members to read issues' do 248 expect(permissions(non_member, issue)).to be_allowed(:read_issue, :read_issue_iid) 249 expect(permissions(non_member, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 250 end 251 252 it 'does not allow non-members to update, admin or set metadata except for set confidential flag' do 253 expect(permissions(non_member, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 254 expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 255 expect(permissions(non_member, new_issue)).to be_disallowed(:set_issue_metadata) 256 # this is allowed for non-members in a public project, as we want to let users report security issues 257 # see https://gitlab.com/gitlab-org/gitlab/-/issues/337665 258 expect(permissions(non_member, new_issue)).to be_allowed(:set_confidentiality) 259 end 260 261 it 'allows support_bot to read issues' do 262 # support_bot is still allowed read access in public projects through :public_access permission, 263 # see project_policy public_access rules policy (rule { can?(:public_access) }.policy {...}) 264 expect(permissions(support_bot, issue)).to be_allowed(:read_issue, :read_issue_iid) 265 expect(permissions(support_bot, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 266 267 expect(permissions(support_bot, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) 268 expect(permissions(support_bot, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 269 270 expect(permissions(support_bot, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality) 271 end 272 273 it_behaves_like 'support bot with service desk enabled' 274 275 context 'when issues are private' do 276 before do 277 project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) 278 end 279 280 let(:issue) { create(:issue, project: project, author: author) } 281 let(:visitor) { create(:user) } 282 let(:admin) { create(:user, :admin) } 283 284 it 'forbids visitors from viewing issues' do 285 expect(permissions(visitor, issue)).to be_disallowed(:read_issue) 286 end 287 it 'forbids visitors from commenting' do 288 expect(permissions(visitor, issue)).to be_disallowed(:create_note) 289 end 290 it 'forbids visitors from subscribing' do 291 expect(permissions(visitor, issue)).to be_disallowed(:update_subscription) 292 end 293 it 'allows guests to view' do 294 expect(permissions(guest, issue)).to be_allowed(:read_issue) 295 end 296 it 'allows guests to comment' do 297 expect(permissions(guest, issue)).to be_allowed(:create_note) 298 end 299 it 'allows guests to subscribe' do 300 expect(permissions(guest, issue)).to be_allowed(:update_subscription) 301 end 302 303 context 'when admin mode is enabled', :enable_admin_mode do 304 it 'allows admins to view' do 305 expect(permissions(admin, issue)).to be_allowed(:read_issue) 306 end 307 308 it 'allows admins to comment' do 309 expect(permissions(admin, issue)).to be_allowed(:create_note) 310 end 311 end 312 313 context 'when admin mode is disabled' do 314 it 'forbids admins to view' do 315 expect(permissions(admin, issue)).to be_disallowed(:read_issue) 316 end 317 318 it 'forbids admins to comment' do 319 expect(permissions(admin, issue)).to be_disallowed(:create_note) 320 end 321 end 322 323 it 'does not allow non-members to update or create issues' do 324 expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 325 expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 326 expect(permissions(non_member, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality) 327 end 328 329 it_behaves_like 'support bot with service desk disabled' 330 it_behaves_like 'support bot with service desk enabled' 331 end 332 333 context 'with confidential issues' do 334 let(:confidential_issue) { create(:issue, :confidential, project: project, assignees: [assignee], author: author) } 335 let(:confidential_issue_no_assignee) { create(:issue, :confidential, project: project) } 336 337 it 'does not allow guests to read confidential issues' do 338 expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 339 expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 340 end 341 342 it 'allows reporters to read, update, and admin confidential issues' do 343 expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 344 expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 345 end 346 347 it 'allows reporter from group links to read, update, and admin confidential issues' do 348 expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) 349 expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 350 end 351 352 it 'allows issue authors to read and update their confidential issues' do 353 expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 354 expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 355 356 expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 357 end 358 359 it 'allows issue assignees to read and update their confidential issues' do 360 expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) 361 expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality) 362 363 expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality) 364 end 365 end 366 367 context 'with a hidden issue' do 368 let(:user) { create(:user) } 369 let(:banned_user) { create(:user, :banned) } 370 let(:admin) { create(:user, :admin)} 371 let(:hidden_issue) { create(:issue, project: project, author: banned_user) } 372 373 it 'does not allow non-admin user to read the issue' do 374 expect(permissions(user, hidden_issue)).not_to be_allowed(:read_issue) 375 end 376 377 it 'allows admin to read the issue', :enable_admin_mode do 378 expect(permissions(admin, hidden_issue)).to be_allowed(:read_issue) 379 end 380 end 381 end 382 383 context 'with external authorization enabled' do 384 let(:user) { create(:user) } 385 let(:project) { create(:project, :public) } 386 let(:issue) { create(:issue, project: project) } 387 let(:policies) { described_class.new(user, issue) } 388 389 before do 390 enable_external_authorization_service_check 391 end 392 393 it 'can read the issue iid without accessing the external service' do 394 expect(::Gitlab::ExternalAuthorization).not_to receive(:access_allowed?) 395 396 expect(policies).to be_allowed(:read_issue_iid) 397 end 398 end 399end 400