diff --git a/CHANGELOG b/CHANGELOG index 71547b387e3..b40186b1669 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,7 @@ v 6.6.0 - Permissions: Developer now can manage issue tracker (modify any issue) - Improve Code Compare page performance - Group avatar - - Pygments.rb replaced with highlight.js + - Pygments.rb replaced with highlight.js - Improve Merge request diff store logic - Improve render performnace for MR show page - Fixed Assembla hardcoded project name @@ -12,6 +12,7 @@ v 6.6.0 - Mobile UI improvements (Drew Blessing) - Fix block/remove UI for admin::users#show page - Show users' group membership on users' activity page + - User pages are visible without login if user is authorized to a public project v 6.5.1 - Fix branch selectbox when create merge request from fork @@ -45,7 +46,7 @@ v6.4.3 v6.4.2 - Fixed wrong behaviour of script/upgrade.rb -v6.4.1 +v6.4.1 - Fixed bug with repository rename - Fixed bug with project transfer diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss index f7241b017b0..f268f2a9845 100644 --- a/app/assets/stylesheets/sections/header.scss +++ b/app/assets/stylesheets/sections/header.scss @@ -56,7 +56,7 @@ header { font-size: 18px; .app_logo { margin-left: -15px; } - .project_name { + .title { display: inline-block; overflow: hidden; text-overflow: ellipsis; @@ -127,7 +127,7 @@ header { * Project / Area name * */ - .project_name { + .title { position: relative; float: left; margin: 0; @@ -227,7 +227,7 @@ header { } } } - .project_name { + .title { a { color: #BBB; &:hover { diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6a5ce62909e..e86601a439e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,11 +1,23 @@ class UsersController < ApplicationController - layout 'navless' + + skip_before_filter :authenticate_user!, only: [:show] + layout :determine_layout def show - @user = User.find_by!(username: params[:username]) - @projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace) + @user = User.find_by_username!(params[:username]) + @projects = @user.authorized_projects.includes(:namespace).select {|project| can?(current_user, :read_project, project)} + if !current_user && @projects.empty? + return authenticate_user! + end @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20) - @title = @user.name end + + def determine_layout + if current_user + 'navless' + else + 'public_users' + end + end end diff --git a/app/views/help/public_access.html.haml b/app/views/help/public_access.html.haml index ba2df8c3553..e1b2a2ce1fa 100644 --- a/app/views/help/public_access.html.haml +++ b/app/views/help/public_access.html.haml @@ -44,3 +44,18 @@ %li Go to your project dashboard %li Click on the "Edit" tab %li Change "Visibility Level" + + %h4 Visibility of users + The public page of users, located at + = succeed "," do + %code u/username + is visible if either: + %ul + %li + You are logged in. + %li + %p + You are logged out, and the target user is authorized to (is Guest, Reporter, etc.) + at least one public project. + %p Otherwise, you will be redirected to the sign in page. + When visiting the public page of an user, you will only see listed projects which you can view yourself. diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 1d181d3519c..5080a1b7ef6 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -6,7 +6,7 @@ = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do %h1 GITLAB %span.separator - %h1.project_name= title + %h1.title= title %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} %span.sr-only Toggle navigation diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml index 65c806a915f..99e11cd2b5c 100644 --- a/app/views/layouts/_public_head_panel.html.haml +++ b/app/views/layouts/_public_head_panel.html.haml @@ -6,11 +6,7 @@ = link_to public_root_path, class: "home" do %h1 GITLAB %span.separator - %h1.project_name - - if @project - = project_title(@project) - - else - Public Projects + %h1.title= title .pull-right = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new' diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml index 8f490f61a9c..fda81b3cc83 100644 --- a/app/views/layouts/public.html.haml +++ b/app/views/layouts/public.html.haml @@ -5,7 +5,6 @@ - if current_user = render "layouts/head_panel", title: "Public Projects" - else - = render "layouts/public_head_panel" - + = render "layouts/public_head_panel", title: "Public Projects" .container.navless-container .content= yield diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml index a8e3236d865..7de2347803a 100644 --- a/app/views/layouts/public_projects.html.haml +++ b/app/views/layouts/public_projects.html.haml @@ -2,8 +2,8 @@ %html{ lang: "en"} = render "layouts/head", title: @project.name_with_namespace %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel" - %nav.main-nav.navbar-collapse.collapse + = render "layouts/public_head_panel", title: @project.name_with_namespace + %nav.main-nav .container= render 'layouts/nav/project' .container .content= yield diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml new file mode 100644 index 00000000000..80709d650da --- /dev/null +++ b/app/views/layouts/public_users.html.haml @@ -0,0 +1,7 @@ +!!! 5 +%html{ lang: "en"} + = render "layouts/head", title: @title + %body{class: "#{app_theme} application", :'data-page' => body_data_page} + = render "layouts/public_head_panel", title: @title + .container.navless-container + .content= yield diff --git a/features/admin/groups.feature b/features/admin/groups.feature index 6fed9a34869..7741307f178 100644 --- a/features/admin/groups.feature +++ b/features/admin/groups.feature @@ -2,7 +2,7 @@ Feature: Admin Groups Background: Given I sign in as an admin And I have group with projects - And Create gitlab user "John" + And Create user "John Doe" And I visit admin groups page Scenario: See group list @@ -17,5 +17,5 @@ Feature: Admin Groups @javascript Scenario: Add user into projects in group When I visit admin group page - When I select user "John" from user list as "Reporter" - Then I should see "John" in team list in every project as "Reporter" + When I select user "John Doe" from user list as "Reporter" + Then I should see "John Doe" in team list in every project as "Reporter" diff --git a/features/group/group.feature b/features/group/group.feature index ca3e67d2c1d..6177263e477 100644 --- a/features/group/group.feature +++ b/features/group/group.feature @@ -21,10 +21,10 @@ Feature: Groups @javascript Scenario: I should add user to projects in Group - Given I have new user "John" + Given Create user "John Doe" When I visit group members page - And I select user "John" from list with role "Reporter" - Then I should see user "John" in team list + And I select user "John Doe" from list with role "Reporter" + Then I should see user "John Doe" in team list Scenario: I should see edit group page When I visit group settings page diff --git a/features/steps/admin/admin_groups.rb b/features/steps/admin/admin_groups.rb index 013fa6da8b4..9c1bcfefb9c 100644 --- a/features/steps/admin/admin_groups.rb +++ b/features/steps/admin/admin_groups.rb @@ -1,6 +1,7 @@ class AdminGroups < Spinach::FeatureSteps include SharedAuthentication include SharedPaths + include SharedUser include SharedActiveTab include Select2Helper @@ -20,10 +21,6 @@ class AdminGroups < Spinach::FeatureSteps @project.team << [current_user, :master] end - And 'Create gitlab user "John"' do - create(:user, name: "John") - end - And 'submit form with new group info' do fill_in 'group_name', with: 'gitlab' fill_in 'group_description', with: 'Group description' @@ -39,8 +36,8 @@ class AdminGroups < Spinach::FeatureSteps current_path.should == admin_group_path(Group.last) end - When 'I select user "John" from user list as "Reporter"' do - user = User.find_by(name: "John") + When 'I select user "John Doe" from user list as "Reporter"' do + user = User.find_by(name: "John Doe") select2(user.id, from: "#user_ids", multiple: true) within "#new_team_member" do select "Reporter", from: "group_access" @@ -48,9 +45,9 @@ class AdminGroups < Spinach::FeatureSteps click_button "Add users into group" end - Then 'I should see "John" in team list in every project as "Reporter"' do + Then 'I should see "John Doe" in team list in every project as "Reporter"' do within ".group-users-list" do - page.should have_content "John" + page.should have_content "John Doe" page.should have_content "Reporter" end end diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index 0b0f401c3ba..686f683314a 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -1,6 +1,7 @@ class Groups < Spinach::FeatureSteps include SharedAuthentication include SharedPaths + include SharedUser include Select2Helper Then 'I should see projects list' do @@ -34,12 +35,8 @@ class Groups < Spinach::FeatureSteps end end - Given 'I have new user "John"' do - create(:user, name: "John") - end - - And 'I select user "John" from list with role "Reporter"' do - user = User.find_by(name: "John") + And 'I select user "John Doe" from list with role "Reporter"' do + user = User.find_by(name: "John Doe") within ".users-group-form" do select2(user.id, from: "#user_ids", multiple: true) select "Reporter", from: "group_access" @@ -47,9 +44,9 @@ class Groups < Spinach::FeatureSteps click_button "Add users into group" end - Then 'I should see user "John" in team list' do + Then 'I should see user "John Doe" in team list' do projects_with_access = find(".ui-box .well-list") - projects_with_access.should have_content("John") + projects_with_access.should have_content("John Doe") end Given 'project from group has issues assigned to me' do diff --git a/features/steps/public/projects_feature.rb b/features/steps/public/projects_feature.rb index 84a5ebbf7a7..eb1d235f435 100644 --- a/features/steps/public/projects_feature.rb +++ b/features/steps/public/projects_feature.rb @@ -3,12 +3,8 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps include SharedPaths include SharedProject - step 'I should see project "Community"' do - page.should have_content "Community" - end - - step 'I should not see project "Enterprise"' do - page.should_not have_content "Enterprise" + step 'public empty project "Empty Public Project"' do + create :empty_project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC end step 'I should see project "Empty Public Project"' do @@ -24,14 +20,6 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps page.should have_content 'README.md' end - step 'public project "Community"' do - create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC - end - - step 'public empty project "Empty Public Project"' do - create :empty_project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC - end - step 'I visit empty project page' do project = Project.find_by(name: 'Empty Public Project') visit project_path(project) @@ -60,10 +48,6 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps end end - step 'private project "Enterprise"' do - create :project, name: 'Enterprise' - end - step 'I visit project "Enterprise" page' do project = Project.find_by(name: 'Enterprise') visit project_path(project) @@ -75,18 +59,6 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps end end - step 'internal project "Internal"' do - create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL - end - - step 'I should see project "Internal"' do - page.should have_content "Internal" - end - - step 'I should not see project "Internal"' do - page.should_not have_content "Internal" - end - step 'I visit project "Internal" page' do project = Project.find_by(name: 'Internal') visit project_path(project) diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index d287121bb84..c1aafc183dc 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -5,6 +5,14 @@ module SharedPaths visit new_project_path end + # ---------------------------------------- + # User + # ---------------------------------------- + + step 'I visit user "John Doe" page' do + visit user_path("john_doe") + end + # ---------------------------------------- # Group # ---------------------------------------- diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 7360482d736..a6354aeaf86 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -65,4 +65,68 @@ module SharedProject def current_project @project ||= Project.first end + + # ---------------------------------------- + # Visibility level + # ---------------------------------------- + + step 'private project "Enterprise"' do + create :project, name: 'Enterprise' + end + + step 'I should see project "Enterprise"' do + page.should have_content "Enterprise" + end + + step 'I should not see project "Enterprise"' do + page.should_not have_content "Enterprise" + end + + step 'internal project "Internal"' do + create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL + end + + step 'I should see project "Internal"' do + page.should have_content "Internal" + end + + step 'I should not see project "Internal"' do + page.should_not have_content "Internal" + end + + step 'public project "Community"' do + create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC + end + + step 'I should see project "Community"' do + page.should have_content "Community" + end + + step 'I should not see project "Community"' do + page.should_not have_content "Community" + end + + step '"John Doe" is authorized to private project "Enterprise"' do + user = User.find_by(name: "John Doe") + user ||= create(:user, name: "John Doe", username: "john_doe") + project = Project.find_by(name: "Enterprise") + project ||= create(:project, name: "Enterprise", namespace: user.namespace) + project.team << [user, :master] + end + + step '"John Doe" is authorized to internal project "Internal"' do + user = User.find_by(name: "John Doe") + user ||= create(:user, name: "John Doe", username: "john_doe") + project = Project.find_by(name: "Internal") + project ||= create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL + project.team << [user, :master] + end + + step '"John Doe" is authorized to public project "Community"' do + user = User.find_by(name: "John Doe") + user ||= create(:user, name: "John Doe", username: "john_doe") + project = Project.find_by(name: "Community") + project ||= create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC + project.team << [user, :master] + end end diff --git a/features/steps/shared/user.rb b/features/steps/shared/user.rb new file mode 100644 index 00000000000..a2bf069a114 --- /dev/null +++ b/features/steps/shared/user.rb @@ -0,0 +1,11 @@ +module SharedUser + include Spinach::DSL + + step 'Create user "John Doe"' do + create(:user, name: "John Doe", username: "john_doe") + end + + step 'I sign in as "John Doe"' do + login_with(User.find_by(name: "John Doe")) + end +end diff --git a/features/steps/user.rb b/features/steps/user.rb new file mode 100644 index 00000000000..5fb248ffcbc --- /dev/null +++ b/features/steps/user.rb @@ -0,0 +1,10 @@ +class Spinach::Features::User < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedUser + include SharedProject + + step 'I should see user "John Doe" page' do + expect(page.title).to match(/^\s*John Doe/) + end +end diff --git a/features/user.feature b/features/user.feature new file mode 100644 index 00000000000..c1c1ddda52b --- /dev/null +++ b/features/user.feature @@ -0,0 +1,69 @@ +Feature: User + Background: + Given Create user "John Doe" + And "John Doe" is authorized to private project "Enterprise" + + # Signed out + + Scenario: I visit user "John Doe" page while not signed in when he is authorized to a public project + Given "John Doe" is authorized to internal project "Internal" + And "John Doe" is authorized to public project "Community" + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should not see project "Enterprise" + And I should not see project "Internal" + And I should see project "Community" + + Scenario: I visit user "John Doe" page while not signed in when he is not authorized to a public project + Given "John Doe" is authorized to internal project "Internal" + When I visit user "John Doe" page + Then I should be redirected to sign in page + + # Signed in as someone else + + Scenario: I visit user "John Doe" page while signed in as someone else when he is authorized to a public project + Given "John Doe" is authorized to public project "Community" + And "John Doe" is authorized to internal project "Internal" + And I sign in as a user + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should not see project "Enterprise" + And I should see project "Internal" + And I should see project "Community" + + Scenario: I visit user "John Doe" page while signed in as someone else when he is not authorized to a public project + Given "John Doe" is authorized to internal project "Internal" + And I sign in as a user + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should not see project "Enterprise" + And I should see project "Internal" + And I should not see project "Community" + + Scenario: I visit user "John Doe" page while signed in as someone else when he is not authorized to a project I can see + Given I sign in as a user + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should not see project "Enterprise" + And I should not see project "Internal" + And I should not see project "Community" + + # Signed in as the user himself + + Scenario: I visit user "John Doe" page while signed in as "John Doe" when he has a public project + Given "John Doe" is authorized to internal project "Internal" + And "John Doe" is authorized to public project "Community" + And I sign in as "John Doe" + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should see project "Enterprise" + And I should see project "Internal" + And I should see project "Community" + + Scenario: I visit user "John Doe" page while signed in as "John Doe" when he has no public project + Given I sign in as "John Doe" + When I visit user "John Doe" page + Then I should see user "John Doe" page + And I should see project "Enterprise" + And I should not see project "Internal" + And I should not see project "Community"