Commit 2fc236177f70244101b285bde8ee6a77f779c0ce
Exists in
master
and in
4 other branches
Merge pull request #3801 from holdtotherod/feature/internally-public-projects
Internally public projects
Showing
8 changed files
with
276 additions
and
4 deletions
Show diff stats
app/controllers/application_controller.rb
| @@ -88,7 +88,7 @@ class ApplicationController < ActionController::Base | @@ -88,7 +88,7 @@ class ApplicationController < ActionController::Base | ||
| 88 | end | 88 | end |
| 89 | 89 | ||
| 90 | def authorize_code_access! | 90 | def authorize_code_access! |
| 91 | - return access_denied! unless can?(current_user, :download_code, project) | 91 | + return access_denied! unless can?(current_user, :download_code, project) or project.public? |
| 92 | end | 92 | end |
| 93 | 93 | ||
| 94 | def authorize_create_team! | 94 | def authorize_create_team! |
app/models/ability.rb
| @@ -37,7 +37,7 @@ class Ability | @@ -37,7 +37,7 @@ class Ability | ||
| 37 | elsif team.reporters.include?(user) | 37 | elsif team.reporters.include?(user) |
| 38 | rules << project_report_rules | 38 | rules << project_report_rules |
| 39 | 39 | ||
| 40 | - elsif team.guests.include?(user) | 40 | + elsif team.guests.include?(user) or project.public? |
| 41 | rules << project_guest_rules | 41 | rules << project_guest_rules |
| 42 | end | 42 | end |
| 43 | 43 |
app/views/projects/_form.html.haml
| @@ -48,7 +48,7 @@ | @@ -48,7 +48,7 @@ | ||
| 48 | Public mode: | 48 | Public mode: |
| 49 | .control-group | 49 | .control-group |
| 50 | = f.label :public, class: 'control-label' do | 50 | = f.label :public, class: 'control-label' do |
| 51 | - %span Public clone access | 51 | + %span Public access |
| 52 | .controls | 52 | .controls |
| 53 | = f.check_box :public | 53 | = f.check_box :public |
| 54 | %span.descr | 54 | %span.descr |
| @@ -56,6 +56,8 @@ | @@ -56,6 +56,8 @@ | ||
| 56 | %em without any | 56 | %em without any |
| 57 | authentication. | 57 | authentication. |
| 58 | It will also be listed on the #{link_to "public access directory", public_root_path}. | 58 | It will also be listed on the #{link_to "public access directory", public_root_path}. |
| 59 | + %em Any | ||
| 60 | + user will have #{link_to "Guest", help_permissions_path} permissions on the repository. | ||
| 59 | 61 | ||
| 60 | %fieldset.features | 62 | %fieldset.features |
| 61 | %legend | 63 | %legend |
app/views/public/projects/index.html.haml
| @@ -9,7 +9,10 @@ | @@ -9,7 +9,10 @@ | ||
| 9 | %li.clearfix | 9 | %li.clearfix |
| 10 | %h5 | 10 | %h5 |
| 11 | %i.icon-share | 11 | %i.icon-share |
| 12 | - = project.name_with_namespace | 12 | + - if current_user |
| 13 | + = link_to_project project | ||
| 14 | + - else | ||
| 15 | + = project.name_with_namespace | ||
| 13 | .pull-right | 16 | .pull-right |
| 14 | %pre.dark.tiny git clone #{project.http_url_to_repo} | 17 | %pre.dark.tiny git clone #{project.http_url_to_repo} |
| 15 | %p.description | 18 | %p.description |
features/steps/shared/paths.rb
| @@ -263,6 +263,14 @@ module SharedPaths | @@ -263,6 +263,14 @@ module SharedPaths | ||
| 263 | visit project_wiki_path(@project, :home) | 263 | visit project_wiki_path(@project, :home) |
| 264 | end | 264 | end |
| 265 | 265 | ||
| 266 | + # ---------------------------------------- | ||
| 267 | + # Public Projects | ||
| 268 | + # ---------------------------------------- | ||
| 269 | + | ||
| 270 | + Given 'I visit the public projects area' do | ||
| 271 | + visit public_root_path | ||
| 272 | + end | ||
| 273 | + | ||
| 266 | def root_ref | 274 | def root_ref |
| 267 | @project.repository.root_ref | 275 | @project.repository.root_ref |
| 268 | end | 276 | end |
spec/features/security/project_access_spec.rb
| @@ -229,4 +229,246 @@ describe "Application access" do | @@ -229,4 +229,246 @@ describe "Application access" do | ||
| 229 | it { should be_denied_for :visitor } | 229 | it { should be_denied_for :visitor } |
| 230 | end | 230 | end |
| 231 | end | 231 | end |
| 232 | + | ||
| 233 | + | ||
| 234 | + describe "PublicProject" do | ||
| 235 | + let(:project) { create(:project_with_code) } | ||
| 236 | + | ||
| 237 | + let(:master) { create(:user) } | ||
| 238 | + let(:guest) { create(:user) } | ||
| 239 | + let(:reporter) { create(:user) } | ||
| 240 | + | ||
| 241 | + let(:admin) { create(:user) } | ||
| 242 | + | ||
| 243 | + before do | ||
| 244 | + # public project | ||
| 245 | + project.public = true | ||
| 246 | + project.save! | ||
| 247 | + | ||
| 248 | + # full access | ||
| 249 | + project.team << [master, :master] | ||
| 250 | + | ||
| 251 | + # readonly | ||
| 252 | + project.team << [reporter, :reporter] | ||
| 253 | + | ||
| 254 | + end | ||
| 255 | + | ||
| 256 | + describe "Project should be public" do | ||
| 257 | + subject { project } | ||
| 258 | + | ||
| 259 | + its(:public?) { should be_true } | ||
| 260 | + end | ||
| 261 | + | ||
| 262 | + describe "GET /project_code" do | ||
| 263 | + subject { project_path(project) } | ||
| 264 | + | ||
| 265 | + it { should be_allowed_for master } | ||
| 266 | + it { should be_allowed_for reporter } | ||
| 267 | + it { should be_allowed_for admin } | ||
| 268 | + it { should be_allowed_for guest } | ||
| 269 | + it { should be_allowed_for :user } | ||
| 270 | + it { should be_denied_for :visitor } | ||
| 271 | + end | ||
| 272 | + | ||
| 273 | + describe "GET /project_code/tree/master" do | ||
| 274 | + subject { project_tree_path(project, project.repository.root_ref) } | ||
| 275 | + | ||
| 276 | + it { should be_allowed_for master } | ||
| 277 | + it { should be_allowed_for reporter } | ||
| 278 | + it { should be_allowed_for :admin } | ||
| 279 | + it { should be_allowed_for guest } | ||
| 280 | + it { should be_allowed_for :user } | ||
| 281 | + it { should be_denied_for :visitor } | ||
| 282 | + end | ||
| 283 | + | ||
| 284 | + describe "GET /project_code/commits/master" do | ||
| 285 | + subject { project_commits_path(project, project.repository.root_ref, limit: 1) } | ||
| 286 | + | ||
| 287 | + it { should be_allowed_for master } | ||
| 288 | + it { should be_allowed_for reporter } | ||
| 289 | + it { should be_allowed_for :admin } | ||
| 290 | + it { should be_allowed_for guest } | ||
| 291 | + it { should be_allowed_for :user } | ||
| 292 | + it { should be_denied_for :visitor } | ||
| 293 | + end | ||
| 294 | + | ||
| 295 | + describe "GET /project_code/commit/:sha" do | ||
| 296 | + subject { project_commit_path(project, project.repository.commit) } | ||
| 297 | + | ||
| 298 | + it { should be_allowed_for master } | ||
| 299 | + it { should be_allowed_for reporter } | ||
| 300 | + it { should be_allowed_for :admin } | ||
| 301 | + it { should be_allowed_for guest } | ||
| 302 | + it { should be_allowed_for :user } | ||
| 303 | + it { should be_denied_for :visitor } | ||
| 304 | + end | ||
| 305 | + | ||
| 306 | + describe "GET /project_code/compare" do | ||
| 307 | + subject { project_compare_index_path(project) } | ||
| 308 | + | ||
| 309 | + it { should be_allowed_for master } | ||
| 310 | + it { should be_allowed_for reporter } | ||
| 311 | + it { should be_allowed_for :admin } | ||
| 312 | + it { should be_allowed_for guest } | ||
| 313 | + it { should be_allowed_for :user } | ||
| 314 | + it { should be_denied_for :visitor } | ||
| 315 | + end | ||
| 316 | + | ||
| 317 | + describe "GET /project_code/team" do | ||
| 318 | + subject { project_team_index_path(project) } | ||
| 319 | + | ||
| 320 | + it { should be_allowed_for master } | ||
| 321 | + it { should be_allowed_for reporter } | ||
| 322 | + it { should be_allowed_for :admin } | ||
| 323 | + it { should be_allowed_for guest } | ||
| 324 | + it { should be_allowed_for :user } | ||
| 325 | + it { should be_denied_for :visitor } | ||
| 326 | + end | ||
| 327 | + | ||
| 328 | + describe "GET /project_code/wall" do | ||
| 329 | + subject { project_wall_path(project) } | ||
| 330 | + | ||
| 331 | + it { should be_allowed_for master } | ||
| 332 | + it { should be_allowed_for reporter } | ||
| 333 | + it { should be_allowed_for :admin } | ||
| 334 | + it { should be_allowed_for guest } | ||
| 335 | + it { should be_allowed_for :user } | ||
| 336 | + it { should be_denied_for :visitor } | ||
| 337 | + end | ||
| 338 | + | ||
| 339 | + describe "GET /project_code/blob" do | ||
| 340 | + before do | ||
| 341 | + commit = project.repository.commit | ||
| 342 | + path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name | ||
| 343 | + @blob_path = project_blob_path(project, File.join(commit.id, path)) | ||
| 344 | + end | ||
| 345 | + | ||
| 346 | + it { @blob_path.should be_allowed_for master } | ||
| 347 | + it { @blob_path.should be_allowed_for reporter } | ||
| 348 | + it { @blob_path.should be_allowed_for :admin } | ||
| 349 | + it { @blob_path.should be_allowed_for guest } | ||
| 350 | + it { @blob_path.should be_allowed_for :user } | ||
| 351 | + it { @blob_path.should be_denied_for :visitor } | ||
| 352 | + end | ||
| 353 | + | ||
| 354 | + describe "GET /project_code/edit" do | ||
| 355 | + subject { edit_project_path(project) } | ||
| 356 | + | ||
| 357 | + it { should be_allowed_for master } | ||
| 358 | + it { should be_denied_for reporter } | ||
| 359 | + it { should be_allowed_for :admin } | ||
| 360 | + it { should be_denied_for guest } | ||
| 361 | + it { should be_denied_for :user } | ||
| 362 | + it { should be_denied_for :visitor } | ||
| 363 | + end | ||
| 364 | + | ||
| 365 | + describe "GET /project_code/deploy_keys" do | ||
| 366 | + subject { project_deploy_keys_path(project) } | ||
| 367 | + | ||
| 368 | + it { should be_allowed_for master } | ||
| 369 | + it { should be_denied_for reporter } | ||
| 370 | + it { should be_allowed_for :admin } | ||
| 371 | + it { should be_denied_for guest } | ||
| 372 | + it { should be_denied_for :user } | ||
| 373 | + it { should be_denied_for :visitor } | ||
| 374 | + end | ||
| 375 | + | ||
| 376 | + describe "GET /project_code/issues" do | ||
| 377 | + subject { project_issues_path(project) } | ||
| 378 | + | ||
| 379 | + it { should be_allowed_for master } | ||
| 380 | + it { should be_allowed_for reporter } | ||
| 381 | + it { should be_allowed_for :admin } | ||
| 382 | + it { should be_allowed_for guest } | ||
| 383 | + it { should be_allowed_for :user } | ||
| 384 | + it { should be_denied_for :visitor } | ||
| 385 | + end | ||
| 386 | + | ||
| 387 | + describe "GET /project_code/snippets" do | ||
| 388 | + subject { project_snippets_path(project) } | ||
| 389 | + | ||
| 390 | + it { should be_allowed_for master } | ||
| 391 | + it { should be_allowed_for reporter } | ||
| 392 | + it { should be_allowed_for :admin } | ||
| 393 | + it { should be_allowed_for guest } | ||
| 394 | + it { should be_allowed_for :user } | ||
| 395 | + it { should be_denied_for :visitor } | ||
| 396 | + end | ||
| 397 | + | ||
| 398 | + describe "GET /project_code/snippets/new" do | ||
| 399 | + subject { new_project_snippet_path(project) } | ||
| 400 | + | ||
| 401 | + it { should be_allowed_for master } | ||
| 402 | + it { should be_allowed_for reporter } | ||
| 403 | + it { should be_allowed_for :admin } | ||
| 404 | + it { should be_denied_for guest } | ||
| 405 | + it { should be_denied_for :user } | ||
| 406 | + it { should be_denied_for :visitor } | ||
| 407 | + end | ||
| 408 | + | ||
| 409 | + describe "GET /project_code/merge_requests" do | ||
| 410 | + subject { project_merge_requests_path(project) } | ||
| 411 | + | ||
| 412 | + it { should be_allowed_for master } | ||
| 413 | + it { should be_allowed_for reporter } | ||
| 414 | + it { should be_allowed_for :admin } | ||
| 415 | + it { should be_allowed_for guest } | ||
| 416 | + it { should be_allowed_for :user } | ||
| 417 | + it { should be_denied_for :visitor } | ||
| 418 | + end | ||
| 419 | + | ||
| 420 | + describe "GET /project_code/repository" do | ||
| 421 | + subject { project_repository_path(project) } | ||
| 422 | + | ||
| 423 | + it { should be_allowed_for master } | ||
| 424 | + it { should be_allowed_for reporter } | ||
| 425 | + it { should be_allowed_for :admin } | ||
| 426 | + it { should be_allowed_for guest } | ||
| 427 | + it { should be_allowed_for :user } | ||
| 428 | + it { should be_denied_for :visitor } | ||
| 429 | + end | ||
| 430 | + | ||
| 431 | + describe "GET /project_code/repository/branches" do | ||
| 432 | + subject { branches_project_repository_path(project) } | ||
| 433 | + | ||
| 434 | + before do | ||
| 435 | + # Speed increase | ||
| 436 | + Project.any_instance.stub(:branches).and_return([]) | ||
| 437 | + end | ||
| 438 | + | ||
| 439 | + it { should be_allowed_for master } | ||
| 440 | + it { should be_allowed_for reporter } | ||
| 441 | + it { should be_allowed_for :admin } | ||
| 442 | + it { should be_allowed_for guest } | ||
| 443 | + it { should be_allowed_for :user } | ||
| 444 | + it { should be_denied_for :visitor } | ||
| 445 | + end | ||
| 446 | + | ||
| 447 | + describe "GET /project_code/repository/tags" do | ||
| 448 | + subject { tags_project_repository_path(project) } | ||
| 449 | + | ||
| 450 | + before do | ||
| 451 | + # Speed increase | ||
| 452 | + Project.any_instance.stub(:tags).and_return([]) | ||
| 453 | + end | ||
| 454 | + | ||
| 455 | + it { should be_allowed_for master } | ||
| 456 | + it { should be_allowed_for reporter } | ||
| 457 | + it { should be_allowed_for :admin } | ||
| 458 | + it { should be_allowed_for guest } | ||
| 459 | + it { should be_allowed_for :user } | ||
| 460 | + it { should be_denied_for :visitor } | ||
| 461 | + end | ||
| 462 | + | ||
| 463 | + describe "GET /project_code/hooks" do | ||
| 464 | + subject { project_hooks_path(project) } | ||
| 465 | + | ||
| 466 | + it { should be_allowed_for master } | ||
| 467 | + it { should be_allowed_for reporter } | ||
| 468 | + it { should be_allowed_for :admin } | ||
| 469 | + it { should be_allowed_for guest } | ||
| 470 | + it { should be_allowed_for :user } | ||
| 471 | + it { should be_denied_for :visitor } | ||
| 472 | + end | ||
| 473 | + end | ||
| 232 | end | 474 | end |