Commit 39aeac71b34648d8c691ff36f577bdacbd3e362f

Authored by Dmitriy Zaporozhets
2 parents aef78288 91571c07

Merge pull request #6177 from cirosantilli/public-user-pages

User pages are public
CHANGELOG
... ... @@ -3,7 +3,7 @@ v 6.6.0
3 3 - Permissions: Developer now can manage issue tracker (modify any issue)
4 4 - Improve Code Compare page performance
5 5 - Group avatar
6   - - Pygments.rb replaced with highlight.js
  6 + - Pygments.rb replaced with highlight.js
7 7 - Improve Merge request diff store logic
8 8 - Improve render performnace for MR show page
9 9 - Fixed Assembla hardcoded project name
... ... @@ -13,6 +13,7 @@ v 6.6.0
13 13 - Mobile UI improvements (Drew Blessing)
14 14 - Fix block/remove UI for admin::users#show page
15 15 - Show users' group membership on users' activity page
  16 + - User pages are visible without login if user is authorized to a public project
16 17  
17 18 v 6.5.1
18 19 - Fix branch selectbox when create merge request from fork
... ... @@ -46,7 +47,7 @@ v6.4.3
46 47 v6.4.2
47 48 - Fixed wrong behaviour of script/upgrade.rb
48 49  
49   -v6.4.1
  50 +v6.4.1
50 51 - Fixed bug with repository rename
51 52 - Fixed bug with project transfer
52 53  
... ...
app/assets/stylesheets/sections/header.scss
... ... @@ -56,7 +56,7 @@ header {
56 56 font-size: 18px;
57 57  
58 58 .app_logo { margin-left: -15px; }
59   - .project_name {
  59 + .title {
60 60 display: inline-block;
61 61 overflow: hidden;
62 62 text-overflow: ellipsis;
... ... @@ -127,7 +127,7 @@ header {
127 127 * Project / Area name
128 128 *
129 129 */
130   - .project_name {
  130 + .title {
131 131 position: relative;
132 132 float: left;
133 133 margin: 0;
... ... @@ -227,7 +227,7 @@ header {
227 227 }
228 228 }
229 229 }
230   - .project_name {
  230 + .title {
231 231 a {
232 232 color: #BBB;
233 233 &:hover {
... ...
app/controllers/users_controller.rb
1 1 class UsersController < ApplicationController
2   - layout 'navless'
  2 +
  3 + skip_before_filter :authenticate_user!, only: [:show]
  4 + layout :determine_layout
3 5  
4 6 def show
5   - @user = User.find_by!(username: params[:username])
6   - @projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace)
  7 + @user = User.find_by_username!(params[:username])
  8 + @projects = @user.authorized_projects.includes(:namespace).select {|project| can?(current_user, :read_project, project)}
  9 + if !current_user && @projects.empty?
  10 + return authenticate_user!
  11 + end
7 12 @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
8   -
9 13 @title = @user.name
10 14 end
  15 +
  16 + def determine_layout
  17 + if current_user
  18 + 'navless'
  19 + else
  20 + 'public_users'
  21 + end
  22 + end
11 23 end
... ...
app/views/help/public_access.html.haml
... ... @@ -44,3 +44,18 @@
44 44 %li Go to your project dashboard
45 45 %li Click on the "Edit" tab
46 46 %li Change "Visibility Level"
  47 +
  48 + %h4 Visibility of users
  49 + The public page of users, located at
  50 + = succeed "," do
  51 + %code u/username
  52 + is visible if either:
  53 + %ul
  54 + %li
  55 + You are logged in.
  56 + %li
  57 + %p
  58 + You are logged out, and the target user is authorized to (is Guest, Reporter, etc.)
  59 + at least one public project.
  60 + %p Otherwise, you will be redirected to the sign in page.
  61 + When visiting the public page of an user, you will only see listed projects which you can view yourself.
... ...
app/views/layouts/_head_panel.html.haml
... ... @@ -6,7 +6,7 @@
6 6 = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do
7 7 %h1 GITLAB
8 8 %span.separator
9   - %h1.project_name= title
  9 + %h1.title= title
10 10  
11 11 %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
12 12 %span.sr-only Toggle navigation
... ...
app/views/layouts/_public_head_panel.html.haml
... ... @@ -6,11 +6,7 @@
6 6 = link_to public_root_path, class: "home" do
7 7 %h1 GITLAB
8 8 %span.separator
9   - %h1.project_name
10   - - if @project
11   - = project_title(@project)
12   - - else
13   - Public Projects
  9 + %h1.title= title
14 10  
15 11 .pull-right
16 12 = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in btn-new'
... ...
app/views/layouts/public.html.haml
... ... @@ -5,7 +5,6 @@
5 5 - if current_user
6 6 = render "layouts/head_panel", title: "Public Projects"
7 7 - else
8   - = render "layouts/public_head_panel"
9   -
  8 + = render "layouts/public_head_panel", title: "Public Projects"
10 9 .container.navless-container
11 10 .content= yield
... ...
app/views/layouts/public_projects.html.haml
... ... @@ -2,8 +2,8 @@
2 2 %html{ lang: "en"}
3 3 = render "layouts/head", title: @project.name_with_namespace
4 4 %body{class: "#{app_theme} application", :'data-page' => body_data_page}
5   - = render "layouts/public_head_panel"
6   - %nav.main-nav.navbar-collapse.collapse
  5 + = render "layouts/public_head_panel", title: @project.name_with_namespace
  6 + %nav.main-nav
7 7 .container= render 'layouts/nav/project'
8 8 .container
9 9 .content= yield
... ...
app/views/layouts/public_users.html.haml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +!!! 5
  2 +%html{ lang: "en"}
  3 + = render "layouts/head", title: @title
  4 + %body{class: "#{app_theme} application", :'data-page' => body_data_page}
  5 + = render "layouts/public_head_panel", title: @title
  6 + .container.navless-container
  7 + .content= yield
... ...
features/admin/groups.feature
... ... @@ -2,7 +2,7 @@ Feature: Admin Groups
2 2 Background:
3 3 Given I sign in as an admin
4 4 And I have group with projects
5   - And Create gitlab user "John"
  5 + And Create user "John Doe"
6 6 And I visit admin groups page
7 7  
8 8 Scenario: See group list
... ... @@ -17,5 +17,5 @@ Feature: Admin Groups
17 17 @javascript
18 18 Scenario: Add user into projects in group
19 19 When I visit admin group page
20   - When I select user "John" from user list as "Reporter"
21   - Then I should see "John" in team list in every project as "Reporter"
  20 + When I select user "John Doe" from user list as "Reporter"
  21 + Then I should see "John Doe" in team list in every project as "Reporter"
... ...
features/group/group.feature
... ... @@ -21,10 +21,10 @@ Feature: Groups
21 21  
22 22 @javascript
23 23 Scenario: I should add user to projects in Group
24   - Given I have new user "John"
  24 + Given Create user "John Doe"
25 25 When I visit group members page
26   - And I select user "John" from list with role "Reporter"
27   - Then I should see user "John" in team list
  26 + And I select user "John Doe" from list with role "Reporter"
  27 + Then I should see user "John Doe" in team list
28 28  
29 29 Scenario: I should see edit group page
30 30 When I visit group settings page
... ...
features/steps/admin/admin_groups.rb
1 1 class AdminGroups < Spinach::FeatureSteps
2 2 include SharedAuthentication
3 3 include SharedPaths
  4 + include SharedUser
4 5 include SharedActiveTab
5 6 include Select2Helper
6 7  
... ... @@ -20,10 +21,6 @@ class AdminGroups &lt; Spinach::FeatureSteps
20 21 @project.team << [current_user, :master]
21 22 end
22 23  
23   - And 'Create gitlab user "John"' do
24   - create(:user, name: "John")
25   - end
26   -
27 24 And 'submit form with new group info' do
28 25 fill_in 'group_name', with: 'gitlab'
29 26 fill_in 'group_description', with: 'Group description'
... ... @@ -39,8 +36,8 @@ class AdminGroups &lt; Spinach::FeatureSteps
39 36 current_path.should == admin_group_path(Group.last)
40 37 end
41 38  
42   - When 'I select user "John" from user list as "Reporter"' do
43   - user = User.find_by(name: "John")
  39 + When 'I select user "John Doe" from user list as "Reporter"' do
  40 + user = User.find_by(name: "John Doe")
44 41 select2(user.id, from: "#user_ids", multiple: true)
45 42 within "#new_team_member" do
46 43 select "Reporter", from: "group_access"
... ... @@ -48,9 +45,9 @@ class AdminGroups &lt; Spinach::FeatureSteps
48 45 click_button "Add users into group"
49 46 end
50 47  
51   - Then 'I should see "John" in team list in every project as "Reporter"' do
  48 + Then 'I should see "John Doe" in team list in every project as "Reporter"' do
52 49 within ".group-users-list" do
53   - page.should have_content "John"
  50 + page.should have_content "John Doe"
54 51 page.should have_content "Reporter"
55 52 end
56 53 end
... ...
features/steps/group/group.rb
1 1 class Groups < Spinach::FeatureSteps
2 2 include SharedAuthentication
3 3 include SharedPaths
  4 + include SharedUser
4 5 include Select2Helper
5 6  
6 7 Then 'I should see projects list' do
... ... @@ -34,12 +35,8 @@ class Groups &lt; Spinach::FeatureSteps
34 35 end
35 36 end
36 37  
37   - Given 'I have new user "John"' do
38   - create(:user, name: "John")
39   - end
40   -
41   - And 'I select user "John" from list with role "Reporter"' do
42   - user = User.find_by(name: "John")
  38 + And 'I select user "John Doe" from list with role "Reporter"' do
  39 + user = User.find_by(name: "John Doe")
43 40 within ".users-group-form" do
44 41 select2(user.id, from: "#user_ids", multiple: true)
45 42 select "Reporter", from: "group_access"
... ... @@ -47,9 +44,9 @@ class Groups &lt; Spinach::FeatureSteps
47 44 click_button "Add users into group"
48 45 end
49 46  
50   - Then 'I should see user "John" in team list' do
  47 + Then 'I should see user "John Doe" in team list' do
51 48 projects_with_access = find(".ui-box .well-list")
52   - projects_with_access.should have_content("John")
  49 + projects_with_access.should have_content("John Doe")
53 50 end
54 51  
55 52 Given 'project from group has issues assigned to me' do
... ...
features/steps/public/projects_feature.rb
... ... @@ -3,12 +3,8 @@ class Spinach::Features::PublicProjectsFeature &lt; Spinach::FeatureSteps
3 3 include SharedPaths
4 4 include SharedProject
5 5  
6   - step 'I should see project "Community"' do
7   - page.should have_content "Community"
8   - end
9   -
10   - step 'I should not see project "Enterprise"' do
11   - page.should_not have_content "Enterprise"
  6 + step 'public empty project "Empty Public Project"' do
  7 + create :empty_project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC
12 8 end
13 9  
14 10 step 'I should see project "Empty Public Project"' do
... ... @@ -24,14 +20,6 @@ class Spinach::Features::PublicProjectsFeature &lt; Spinach::FeatureSteps
24 20 page.should have_content 'README.md'
25 21 end
26 22  
27   - step 'public project "Community"' do
28   - create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
29   - end
30   -
31   - step 'public empty project "Empty Public Project"' do
32   - create :empty_project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC
33   - end
34   -
35 23 step 'I visit empty project page' do
36 24 project = Project.find_by(name: 'Empty Public Project')
37 25 visit project_path(project)
... ... @@ -60,10 +48,6 @@ class Spinach::Features::PublicProjectsFeature &lt; Spinach::FeatureSteps
60 48 end
61 49 end
62 50  
63   - step 'private project "Enterprise"' do
64   - create :project, name: 'Enterprise'
65   - end
66   -
67 51 step 'I visit project "Enterprise" page' do
68 52 project = Project.find_by(name: 'Enterprise')
69 53 visit project_path(project)
... ... @@ -75,18 +59,6 @@ class Spinach::Features::PublicProjectsFeature &lt; Spinach::FeatureSteps
75 59 end
76 60 end
77 61  
78   - step 'internal project "Internal"' do
79   - create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
80   - end
81   -
82   - step 'I should see project "Internal"' do
83   - page.should have_content "Internal"
84   - end
85   -
86   - step 'I should not see project "Internal"' do
87   - page.should_not have_content "Internal"
88   - end
89   -
90 62 step 'I visit project "Internal" page' do
91 63 project = Project.find_by(name: 'Internal')
92 64 visit project_path(project)
... ...
features/steps/shared/paths.rb
... ... @@ -6,6 +6,14 @@ module SharedPaths
6 6 end
7 7  
8 8 # ----------------------------------------
  9 + # User
  10 + # ----------------------------------------
  11 +
  12 + step 'I visit user "John Doe" page' do
  13 + visit user_path("john_doe")
  14 + end
  15 +
  16 + # ----------------------------------------
9 17 # Group
10 18 # ----------------------------------------
11 19  
... ...
features/steps/shared/project.rb
... ... @@ -65,4 +65,68 @@ module SharedProject
65 65 def current_project
66 66 @project ||= Project.first
67 67 end
  68 +
  69 + # ----------------------------------------
  70 + # Visibility level
  71 + # ----------------------------------------
  72 +
  73 + step 'private project "Enterprise"' do
  74 + create :project, name: 'Enterprise'
  75 + end
  76 +
  77 + step 'I should see project "Enterprise"' do
  78 + page.should have_content "Enterprise"
  79 + end
  80 +
  81 + step 'I should not see project "Enterprise"' do
  82 + page.should_not have_content "Enterprise"
  83 + end
  84 +
  85 + step 'internal project "Internal"' do
  86 + create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
  87 + end
  88 +
  89 + step 'I should see project "Internal"' do
  90 + page.should have_content "Internal"
  91 + end
  92 +
  93 + step 'I should not see project "Internal"' do
  94 + page.should_not have_content "Internal"
  95 + end
  96 +
  97 + step 'public project "Community"' do
  98 + create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
  99 + end
  100 +
  101 + step 'I should see project "Community"' do
  102 + page.should have_content "Community"
  103 + end
  104 +
  105 + step 'I should not see project "Community"' do
  106 + page.should_not have_content "Community"
  107 + end
  108 +
  109 + step '"John Doe" is authorized to private project "Enterprise"' do
  110 + user = User.find_by(name: "John Doe")
  111 + user ||= create(:user, name: "John Doe", username: "john_doe")
  112 + project = Project.find_by(name: "Enterprise")
  113 + project ||= create(:project, name: "Enterprise", namespace: user.namespace)
  114 + project.team << [user, :master]
  115 + end
  116 +
  117 + step '"John Doe" is authorized to internal project "Internal"' do
  118 + user = User.find_by(name: "John Doe")
  119 + user ||= create(:user, name: "John Doe", username: "john_doe")
  120 + project = Project.find_by(name: "Internal")
  121 + project ||= create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
  122 + project.team << [user, :master]
  123 + end
  124 +
  125 + step '"John Doe" is authorized to public project "Community"' do
  126 + user = User.find_by(name: "John Doe")
  127 + user ||= create(:user, name: "John Doe", username: "john_doe")
  128 + project = Project.find_by(name: "Community")
  129 + project ||= create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
  130 + project.team << [user, :master]
  131 + end
68 132 end
... ...
features/steps/shared/user.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +module SharedUser
  2 + include Spinach::DSL
  3 +
  4 + step 'Create user "John Doe"' do
  5 + create(:user, name: "John Doe", username: "john_doe")
  6 + end
  7 +
  8 + step 'I sign in as "John Doe"' do
  9 + login_with(User.find_by(name: "John Doe"))
  10 + end
  11 +end
... ...
features/steps/user.rb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +class Spinach::Features::User < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedPaths
  4 + include SharedUser
  5 + include SharedProject
  6 +
  7 + step 'I should see user "John Doe" page' do
  8 + expect(page.title).to match(/^\s*John Doe/)
  9 + end
  10 +end
... ...
features/user.feature 0 → 100644
... ... @@ -0,0 +1,69 @@
  1 +Feature: User
  2 + Background:
  3 + Given Create user "John Doe"
  4 + And "John Doe" is authorized to private project "Enterprise"
  5 +
  6 + # Signed out
  7 +
  8 + Scenario: I visit user "John Doe" page while not signed in when he is authorized to a public project
  9 + Given "John Doe" is authorized to internal project "Internal"
  10 + And "John Doe" is authorized to public project "Community"
  11 + When I visit user "John Doe" page
  12 + Then I should see user "John Doe" page
  13 + And I should not see project "Enterprise"
  14 + And I should not see project "Internal"
  15 + And I should see project "Community"
  16 +
  17 + Scenario: I visit user "John Doe" page while not signed in when he is not authorized to a public project
  18 + Given "John Doe" is authorized to internal project "Internal"
  19 + When I visit user "John Doe" page
  20 + Then I should be redirected to sign in page
  21 +
  22 + # Signed in as someone else
  23 +
  24 + Scenario: I visit user "John Doe" page while signed in as someone else when he is authorized to a public project
  25 + Given "John Doe" is authorized to public project "Community"
  26 + And "John Doe" is authorized to internal project "Internal"
  27 + And I sign in as a user
  28 + When I visit user "John Doe" page
  29 + Then I should see user "John Doe" page
  30 + And I should not see project "Enterprise"
  31 + And I should see project "Internal"
  32 + And I should see project "Community"
  33 +
  34 + Scenario: I visit user "John Doe" page while signed in as someone else when he is not authorized to a public project
  35 + Given "John Doe" is authorized to internal project "Internal"
  36 + And I sign in as a user
  37 + When I visit user "John Doe" page
  38 + Then I should see user "John Doe" page
  39 + And I should not see project "Enterprise"
  40 + And I should see project "Internal"
  41 + And I should not see project "Community"
  42 +
  43 + Scenario: I visit user "John Doe" page while signed in as someone else when he is not authorized to a project I can see
  44 + Given I sign in as a user
  45 + When I visit user "John Doe" page
  46 + Then I should see user "John Doe" page
  47 + And I should not see project "Enterprise"
  48 + And I should not see project "Internal"
  49 + And I should not see project "Community"
  50 +
  51 + # Signed in as the user himself
  52 +
  53 + Scenario: I visit user "John Doe" page while signed in as "John Doe" when he has a public project
  54 + Given "John Doe" is authorized to internal project "Internal"
  55 + And "John Doe" is authorized to public project "Community"
  56 + And I sign in as "John Doe"
  57 + When I visit user "John Doe" page
  58 + Then I should see user "John Doe" page
  59 + And I should see project "Enterprise"
  60 + And I should see project "Internal"
  61 + And I should see project "Community"
  62 +
  63 + Scenario: I visit user "John Doe" page while signed in as "John Doe" when he has no public project
  64 + Given I sign in as "John Doe"
  65 + When I visit user "John Doe" page
  66 + Then I should see user "John Doe" page
  67 + And I should see project "Enterprise"
  68 + And I should not see project "Internal"
  69 + And I should not see project "Community"
... ...