Commit 39aeac71b34648d8c691ff36f577bdacbd3e362f
Exists in
spb-stable
and in
3 other branches
Merge pull request #6177 from cirosantilli/public-user-pages
User pages are public
Showing
19 changed files
with
229 additions
and
71 deletions
Show diff stats
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
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 | ... | ... |
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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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" | ... | ... |