Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
99011a61
Commit
99011a61
authored
Jul 24, 2018
by
JX Terry
Committed by
Douwe Maan
Jul 24, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add an option to have a private profile on GitLab
parent
adc327d3
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
312 additions
and
66 deletions
+312
-66
app/controllers/profiles_controller.rb
app/controllers/profiles_controller.rb
+2
-1
app/controllers/users_controller.rb
app/controllers/users_controller.rb
+6
-0
app/finders/personal_projects_finder.rb
app/finders/personal_projects_finder.rb
+4
-0
app/finders/user_recent_events_finder.rb
app/finders/user_recent_events_finder.rb
+3
-0
app/helpers/users_helper.rb
app/helpers/users_helper.rb
+7
-1
app/policies/user_policy.rb
app/policies/user_policy.rb
+6
-0
app/services/users/build_service.rb
app/services/users/build_service.rb
+2
-1
app/views/profiles/show.html.haml
app/views/profiles/show.html.haml
+6
-0
app/views/users/show.html.haml
app/views/users/show.html.haml
+44
-30
changelogs/unreleased/38604-add-private-profile.yml
changelogs/unreleased/38604-add-private-profile.yml
+5
-0
db/migrate/20180722103201_add_private_profile_to_users.rb
db/migrate/20180722103201_add_private_profile_to_users.rb
+10
-0
db/schema.rb
db/schema.rb
+2
-1
doc/api/users.md
doc/api/users.md
+12
-5
doc/user/profile/index.md
doc/user/profile/index.md
+22
-0
lib/api/entities.rb
lib/api/entities.rb
+2
-1
lib/api/keys.rb
lib/api/keys.rb
+1
-1
lib/api/users.rb
lib/api/users.rb
+6
-5
spec/controllers/users_controller_spec.rb
spec/controllers/users_controller_spec.rb
+57
-7
spec/features/users/show_spec.rb
spec/features/users/show_spec.rb
+47
-9
spec/finders/user_recent_events_finder_spec.rb
spec/finders/user_recent_events_finder_spec.rb
+13
-2
spec/helpers/users_helper_spec.rb
spec/helpers/users_helper_spec.rb
+14
-2
spec/requests/api/users_spec.rb
spec/requests/api/users_spec.rb
+41
-0
No files found.
app/controllers/profiles_controller.rb
View file @
99011a61
...
@@ -99,7 +99,8 @@ class ProfilesController < Profiles::ApplicationController
...
@@ -99,7 +99,8 @@ class ProfilesController < Profiles::ApplicationController
:username
,
:username
,
:website_url
,
:website_url
,
:organization
,
:organization
,
:preferred_language
:preferred_language
,
:private_profile
)
)
end
end
end
end
app/controllers/users_controller.rb
View file @
99011a61
...
@@ -13,6 +13,8 @@ class UsersController < ApplicationController
...
@@ -13,6 +13,8 @@ class UsersController < ApplicationController
skip_before_action
:authenticate_user!
skip_before_action
:authenticate_user!
before_action
:user
,
except:
[
:exists
]
before_action
:user
,
except:
[
:exists
]
before_action
:authorize_read_user_profile!
,
only:
[
:calendar
,
:calendar_activities
,
:groups
,
:projects
,
:contributed_projects
,
:snippets
]
def
show
def
show
respond_to
do
|
format
|
respond_to
do
|
format
|
...
@@ -148,4 +150,8 @@ class UsersController < ApplicationController
...
@@ -148,4 +150,8 @@ class UsersController < ApplicationController
def
build_canonical_path
(
user
)
def
build_canonical_path
(
user
)
url_for
(
safe_params
.
merge
(
username:
user
.
to_param
))
url_for
(
safe_params
.
merge
(
username:
user
.
to_param
))
end
end
def
authorize_read_user_profile!
access_denied!
unless
can?
(
current_user
,
:read_user_profile
,
user
)
end
end
end
app/finders/personal_projects_finder.rb
View file @
99011a61
class
PersonalProjectsFinder
<
UnionFinder
class
PersonalProjectsFinder
<
UnionFinder
include
Gitlab
::
Allowable
def
initialize
(
user
,
params
=
{})
def
initialize
(
user
,
params
=
{})
@user
=
user
@user
=
user
@params
=
params
@params
=
params
...
@@ -14,6 +16,8 @@ class PersonalProjectsFinder < UnionFinder
...
@@ -14,6 +16,8 @@ class PersonalProjectsFinder < UnionFinder
#
#
# Returns an ActiveRecord::Relation.
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
)
def
execute
(
current_user
=
nil
)
return
Project
.
none
unless
can?
(
current_user
,
:read_user_profile
,
@user
)
segments
=
all_projects
(
current_user
)
segments
=
all_projects
(
current_user
)
find_union
(
segments
,
Project
).
includes
(
:namespace
).
order_updated_desc
find_union
(
segments
,
Project
).
includes
(
:namespace
).
order_updated_desc
...
...
app/finders/user_recent_events_finder.rb
View file @
99011a61
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
class
UserRecentEventsFinder
class
UserRecentEventsFinder
prepend
FinderWithCrossProjectAccess
prepend
FinderWithCrossProjectAccess
include
FinderMethods
include
FinderMethods
include
Gitlab
::
Allowable
requires_cross_project_access
requires_cross_project_access
...
@@ -21,6 +22,8 @@ class UserRecentEventsFinder
...
@@ -21,6 +22,8 @@ class UserRecentEventsFinder
end
end
def
execute
def
execute
return
Event
.
none
unless
can?
(
current_user
,
:read_user_profile
,
target_user
)
recent_events
(
params
[
:offset
]
||
0
)
recent_events
(
params
[
:offset
]
||
0
)
.
joins
(
:project
)
.
joins
(
:project
)
.
with_associations
.
with_associations
...
...
app/helpers/users_helper.rb
View file @
99011a61
...
@@ -42,7 +42,13 @@ module UsersHelper
...
@@ -42,7 +42,13 @@ module UsersHelper
private
private
def
get_profile_tabs
def
get_profile_tabs
[
:activity
,
:groups
,
:contributed
,
:projects
,
:snippets
]
tabs
=
[]
if
can?
(
current_user
,
:read_user_profile
,
@user
)
tabs
+=
[
:activity
,
:groups
,
:contributed
,
:projects
,
:snippets
]
end
tabs
end
end
def
get_current_user_menu_items
def
get_current_user_menu_items
...
...
app/policies/user_policy.rb
View file @
99011a61
...
@@ -5,6 +5,9 @@ class UserPolicy < BasePolicy
...
@@ -5,6 +5,9 @@ class UserPolicy < BasePolicy
desc
"This is the ghost user"
desc
"This is the ghost user"
condition
(
:subject_ghost
,
scope: :subject
,
score:
0
)
{
@subject
.
ghost?
}
condition
(
:subject_ghost
,
scope: :subject
,
score:
0
)
{
@subject
.
ghost?
}
desc
"The profile is private"
condition
(
:private_profile
,
scope: :subject
,
score:
0
)
{
@subject
.
private_profile?
}
rule
{
~
restricted_public_level
}.
enable
:read_user
rule
{
~
restricted_public_level
}.
enable
:read_user
rule
{
~
anonymous
}.
enable
:read_user
rule
{
~
anonymous
}.
enable
:read_user
...
@@ -12,4 +15,7 @@ class UserPolicy < BasePolicy
...
@@ -12,4 +15,7 @@ class UserPolicy < BasePolicy
enable
:destroy_user
enable
:destroy_user
enable
:update_user
enable
:update_user
end
end
rule
{
default
}.
enable
:read_user_profile
rule
{
private_profile
&
~
(
user_is_self
|
admin
)
}.
prevent
:read_user_profile
end
end
app/services/users/build_service.rb
View file @
99011a61
...
@@ -64,7 +64,8 @@ module Users
...
@@ -64,7 +64,8 @@ module Users
:theme_id
,
:theme_id
,
:twitter
,
:twitter
,
:username
,
:username
,
:website_url
:website_url
,
:private_profile
]
]
end
end
...
...
app/views/profiles/show.html.haml
View file @
99011a61
...
@@ -69,6 +69,12 @@
...
@@ -69,6 +69,12 @@
=
f
.
text_field
:location
=
f
.
text_field
:location
=
f
.
text_field
:organization
=
f
.
text_field
:organization
=
f
.
text_area
:bio
,
rows:
4
,
maxlength:
250
,
help:
'Tell us about yourself in fewer than 250 characters.'
=
f
.
text_area
:bio
,
rows:
4
,
maxlength:
250
,
help:
'Tell us about yourself in fewer than 250 characters.'
%hr
%h5
Private profile
-
private_profile_label
=
capture
do
Don't display activity-related personal information on your profile
=
link_to
icon
(
'question-circle'
),
help_page_path
(
'user/profile/index.md'
,
anchor:
'private-profile'
)
=
f
.
check_box
:private_profile
,
label:
private_profile_label
.prepend-top-default.append-bottom-default
.prepend-top-default.append-bottom-default
=
f
.
submit
'Update profile settings'
,
class:
'btn btn-success'
=
f
.
submit
'Update profile settings'
,
class:
'btn btn-success'
=
link_to
'Cancel'
,
user_path
(
current_user
),
class:
'btn btn-cancel'
=
link_to
'Cancel'
,
user_path
(
current_user
),
class:
'btn btn-cancel'
...
...
app/views/users/show.html.haml
View file @
99011a61
...
@@ -23,8 +23,9 @@
...
@@ -23,8 +23,9 @@
=
link_to
new_abuse_report_path
(
user_id:
@user
.
id
,
ref_url:
request
.
referrer
),
class:
'btn'
,
=
link_to
new_abuse_report_path
(
user_id:
@user
.
id
,
ref_url:
request
.
referrer
),
class:
'btn'
,
title:
'Report abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'bottom'
,
container:
'body'
}
do
title:
'Report abuse'
,
data:
{
toggle:
'tooltip'
,
placement:
'bottom'
,
container:
'body'
}
do
=
icon
(
'exclamation-circle'
)
=
icon
(
'exclamation-circle'
)
=
link_to
user_path
(
@user
,
rss_url_options
),
class:
'btn btn-default has-tooltip'
,
title:
'Subscribe'
,
'aria-label'
:
'Subscribe'
do
-
if
can?
(
current_user
,
:read_user_profile
,
@user
)
=
icon
(
'rss'
)
=
link_to
user_path
(
@user
,
rss_url_options
),
class:
'btn btn-default has-tooltip'
,
title:
'Subscribe'
,
'aria-label'
:
'Subscribe'
do
=
icon
(
'rss'
)
-
if
current_user
&&
current_user
.
admin?
-
if
current_user
&&
current_user
.
admin?
=
link_to
[
:admin
,
@user
],
class:
'btn btn-default'
,
title:
'View user in admin area'
,
=
link_to
[
:admin
,
@user
],
class:
'btn btn-default'
,
title:
'View user in admin area'
,
data:
{
toggle:
'tooltip'
,
placement:
'bottom'
,
container:
'body'
}
do
data:
{
toggle:
'tooltip'
,
placement:
'bottom'
,
container:
'body'
}
do
...
@@ -40,10 +41,12 @@
...
@@ -40,10 +41,12 @@
=
@user
.
name
=
@user
.
name
.cover-desc.member-date
.cover-desc.member-date
%span
.middle-dot-divider
%p
@
#{
@user
.
username
}
%span
.middle-dot-divider
%span
.middle-dot-divider
@
#{
@user
.
username
}
Member since
#{
@user
.
created_at
.
to_date
.
to_s
(
:long
)
}
-
if
can?
(
current_user
,
:read_user_profile
,
@user
)
%span
.middle-dot-divider
Member since
#{
@user
.
created_at
.
to_date
.
to_s
(
:long
)
}
.cover-desc
.cover-desc
-
unless
@user
.
public_email
.
blank?
-
unless
@user
.
public_email
.
blank?
...
@@ -78,30 +81,31 @@
...
@@ -78,30 +81,31 @@
%p
.profile-user-bio
%p
.profile-user-bio
=
@user
.
bio
=
@user
.
bio
.scrolling-tabs-container
-
unless
profile_tabs
.
empty?
.fade-left
=
icon
(
'angle-left'
)
.scrolling-tabs-container
.fade-right
=
icon
(
'angle-right'
)
.fade-left
=
icon
(
'angle-left'
)
%ul
.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs
.fade-right
=
icon
(
'angle-right'
)
-
if
profile_tab?
(
:activity
)
%ul
.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs
%li
.js-activity-tab
-
if
profile_tab?
(
:activity
)
=
link_to
user_path
,
data:
{
target:
'div#activity'
,
action:
'activity'
,
toggle:
'tab'
}
do
%li
.js-activity-tab
Activity
=
link_to
user_path
,
data:
{
target:
'div#activity'
,
action:
'activity'
,
toggle:
'tab'
}
do
-
if
profile_tab?
(
:groups
)
Activity
%li
.js-groups-tab
-
if
profile_tab?
(
:groups
)
=
link_to
user_groups_path
,
data:
{
target:
'div#groups'
,
action:
'groups'
,
toggle:
'tab'
,
endpoint:
user_groups_path
(
format: :json
)
}
do
%li
.js-groups-tab
Groups
=
link_to
user_groups_path
,
data:
{
target:
'div#groups'
,
action:
'groups'
,
toggle:
'tab'
,
endpoint:
user_groups_path
(
format: :json
)
}
do
-
if
profile_tab?
(
:contributed
)
Groups
%li
.js-contributed-tab
-
if
profile_tab?
(
:contributed
)
=
link_to
user_contributed_projects_path
,
data:
{
target:
'div#contributed'
,
action:
'contributed'
,
toggle:
'tab'
,
endpoint:
user_contributed_projects_path
(
format: :json
)
}
do
%li
.js-contributed-tab
Contributed projects
=
link_to
user_contributed_projects_path
,
data:
{
target:
'div#contributed'
,
action:
'contributed'
,
toggle:
'tab'
,
endpoint:
user_contributed_projects_path
(
format: :json
)
}
do
-
if
profile_tab?
(
:projects
)
Contributed projects
%li
.js-projects-tab
-
if
profile_tab?
(
:projects
)
=
link_to
user_projects_path
,
data:
{
target:
'div#projects'
,
action:
'projects'
,
toggle:
'tab'
,
endpoint:
user_projects_path
(
format: :json
)
}
do
%li
.js-projects-tab
Personal projects
=
link_to
user_projects_path
,
data:
{
target:
'div#projects'
,
action:
'projects'
,
toggle:
'tab'
,
endpoint:
user_projects_path
(
format: :json
)
}
do
-
if
profile_tab?
(
:snippets
)
Personal projects
%li
.js-snippets-tab
-
if
profile_tab?
(
:snippets
)
=
link_to
user_snippets_path
,
data:
{
target:
'div#snippets'
,
action:
'snippets'
,
toggle:
'tab'
,
endpoint:
user_snippets_path
(
format: :json
)
}
do
%li
.js-snippets-tab
Snippets
=
link_to
user_snippets_path
,
data:
{
target:
'div#snippets'
,
action:
'snippets'
,
toggle:
'tab'
,
endpoint:
user_snippets_path
(
format: :json
)
}
do
Snippets
%div
{
class:
container_class
}
%div
{
class:
container_class
}
.tab-content
.tab-content
...
@@ -137,3 +141,13 @@
...
@@ -137,3 +141,13 @@
.loading-status
.loading-status
=
spinner
=
spinner
-
if
profile_tabs
.
empty?
.row
.col-12
.svg-content
=
image_tag
'illustrations/profile_private_mode.svg'
.col-12.text-center
.text-content
%h4
This user has a private profile
changelogs/unreleased/38604-add-private-profile.yml
0 → 100644
View file @
99011a61
---
title
:
Add an option to have a private profile on GitLab.
merge_request
:
20387
author
:
jxterry
type
:
added
db/migrate/20180722103201_add_private_profile_to_users.rb
0 → 100644
View file @
99011a61
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
AddPrivateProfileToUsers
<
ActiveRecord
::
Migration
DOWNTIME
=
false
def
change
add_column
:users
,
:private_profile
,
:boolean
end
end
db/schema.rb
View file @
99011a61
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201807
04204006
)
do
ActiveRecord
::
Schema
.
define
(
version:
201807
22103201
)
do
# These are extensions that must be enabled in order to support this database
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
enable_extension
"plpgsql"
...
@@ -2124,6 +2124,7 @@ ActiveRecord::Schema.define(version: 20180704204006) do
...
@@ -2124,6 +2124,7 @@ ActiveRecord::Schema.define(version: 20180704204006) do
t
.
integer
"theme_id"
,
limit:
2
t
.
integer
"theme_id"
,
limit:
2
t
.
integer
"accepted_term_id"
t
.
integer
"accepted_term_id"
t
.
string
"feed_token"
t
.
string
"feed_token"
t
.
boolean
"private_profile"
end
end
add_index
"users"
,
[
"admin"
],
name:
"index_users_on_admin"
,
using: :btree
add_index
"users"
,
[
"admin"
],
name:
"index_users_on_admin"
,
using: :btree
...
...
doc/api/users.md
View file @
99011a61
...
@@ -105,7 +105,8 @@ GET /users
...
@@ -105,7 +105,8 @@ GET /users
"can_create_group"
:
true
,
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
true
,
"two_factor_enabled"
:
true
,
"external"
:
false
"external"
:
false
,
"private_profile"
:
false
},
},
{
{
"id"
:
2
,
"id"
:
2
,
...
@@ -135,7 +136,8 @@ GET /users
...
@@ -135,7 +136,8 @@ GET /users
"can_create_group"
:
true
,
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
true
,
"two_factor_enabled"
:
true
,
"external"
:
false
"external"
:
false
,
"private_profile"
:
false
}
}
]
]
```
```
...
@@ -248,7 +250,8 @@ Parameters:
...
@@ -248,7 +250,8 @@ Parameters:
"can_create_group"
:
true
,
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
true
,
"two_factor_enabled"
:
true
,
"external"
:
false
"external"
:
false
,
"private_profile"
:
false
}
}
```
```
...
@@ -288,6 +291,7 @@ Parameters:
...
@@ -288,6 +291,7 @@ Parameters:
-
`skip_confirmation`
(optional) - Skip confirmation - true or false (default)
-
`skip_confirmation`
(optional) - Skip confirmation - true or false (default)
-
`external`
(optional) - Flags the user as external - true or false(default)
-
`external`
(optional) - Flags the user as external - true or false(default)
-
`avatar`
(optional) - Image file for user's avatar
-
`avatar`
(optional) - Image file for user's avatar
-
`private_profile (optional) - User's profile is private - true or false
## User modification
## User modification
...
@@ -318,6 +322,7 @@ Parameters:
...
@@ -318,6 +322,7 @@ Parameters:
- `
skip_reconfirmation
` (optional) - Skip reconfirmation - true or false (default)
- `
skip_reconfirmation
` (optional) - Skip reconfirmation - true or false (default)
- `
external
` (optional) - Flags the user as external - true or false(default)
- `
external
` (optional) - Flags the user as external - true or false(default)
- `
avatar
` (optional) - Image file for user's avatar
- `
avatar
` (optional) - Image file for user's avatar
- `
private_profile (optional) - User's profile is private - true or false
On password update, user will be forced to change it upon next login.
On password update, user will be forced to change it upon next login.
Note, at the moment this method does only return a
`404`
error,
Note, at the moment this method does only return a
`404`
error,
...
@@ -382,7 +387,8 @@ GET /user
...
@@ -382,7 +387,8 @@ GET /user
"can_create_group"
:
true
,
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
true
,
"two_factor_enabled"
:
true
,
"external"
:
false
"external"
:
false
,
"private_profile"
:
false
}
}
```
```
...
@@ -429,7 +435,8 @@ GET /user
...
@@ -429,7 +435,8 @@ GET /user
"can_create_group"
:
true
,
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
true
,
"two_factor_enabled"
:
true
,
"external"
:
false
"external"
:
false
,
"private_profile"
:
false
}
}
```
```
...
...
doc/user/profile/index.md
View file @
99011a61
...
@@ -68,6 +68,28 @@ Alternatively, you can follow [this detailed procedure from the GitLab Team Hand
...
@@ -68,6 +68,28 @@ Alternatively, you can follow [this detailed procedure from the GitLab Team Hand
which also covers the case where you have projects hosted with
which also covers the case where you have projects hosted with
[
GitLab Pages
](
../project/pages/index.md
)
.
[
GitLab Pages
](
../project/pages/index.md
)
.
## Private profile
The following information will be hidden from the user profile page (https://gitlab.example.com/username) if this feature is enabled:
-
Atom feed
-
Date when account is created
-
Activity tab
-
Groups tab
-
Contributed projects tab
-
Personal projects tab
-
Snippets tab
To enable private profile:
1.
Navigate to your personal
[
profile settings
](
#profile-settings
)
.
1.
Check the "Private profile" option.
1.
Hit
**Update profile settings**
.
NOTE:
**Note:**
You and GitLab admins can see your the abovementioned information on your profile even if it is private.
## Troubleshooting
## Troubleshooting
### Why do I keep getting signed out?
### Why do I keep getting signed out?
...
...
lib/api/entities.rb
View file @
99011a61
...
@@ -30,7 +30,7 @@ module API
...
@@ -30,7 +30,7 @@ module API
end
end
class
User
<
UserBasic
class
User
<
UserBasic
expose
:created_at
expose
:created_at
,
if:
->
(
user
,
opts
)
{
Ability
.
allowed?
(
opts
[
:current_user
],
:read_user_profile
,
user
)
}
expose
:bio
,
:location
,
:skype
,
:linkedin
,
:twitter
,
:website_url
,
:organization
expose
:bio
,
:location
,
:skype
,
:linkedin
,
:twitter
,
:website_url
,
:organization
end
end
...
@@ -55,6 +55,7 @@ module API
...
@@ -55,6 +55,7 @@ module API
expose
:can_create_project?
,
as: :can_create_project
expose
:can_create_project?
,
as: :can_create_project
expose
:two_factor_enabled?
,
as: :two_factor_enabled
expose
:two_factor_enabled?
,
as: :two_factor_enabled
expose
:external
expose
:external
expose
:private_profile
end
end
class
UserWithAdmin
<
UserPublic
class
UserWithAdmin
<
UserPublic
...
...
lib/api/keys.rb
View file @
99011a61
...
@@ -12,7 +12,7 @@ module API
...
@@ -12,7 +12,7 @@ module API
key
=
Key
.
find
(
params
[
:id
])
key
=
Key
.
find
(
params
[
:id
])
present
key
,
with:
Entities
::
SSHKeyWithUser
present
key
,
with:
Entities
::
SSHKeyWithUser
,
current_user:
current_user
end
end
end
end
end
end
...
...
lib/api/users.rb
View file @
99011a61
...
@@ -42,6 +42,7 @@ module API
...
@@ -42,6 +42,7 @@ module API
optional
:can_create_group
,
type:
Boolean
,
desc:
'Flag indicating the user can create groups'
optional
:can_create_group
,
type:
Boolean
,
desc:
'Flag indicating the user can create groups'
optional
:external
,
type:
Boolean
,
desc:
'Flag indicating the user is an external user'
optional
:external
,
type:
Boolean
,
desc:
'Flag indicating the user is an external user'
optional
:avatar
,
type:
File
,
desc:
'Avatar image for user'
optional
:avatar
,
type:
File
,
desc:
'Avatar image for user'
optional
:private_profile
,
type:
Boolean
,
desc:
'Flag indicating the user has a private profile'
optional
:min_access_level
,
type:
Integer
,
values:
Gitlab
::
Access
.
all_values
,
desc:
'Limit by minimum access level of authenticated user'
optional
:min_access_level
,
type:
Integer
,
values:
Gitlab
::
Access
.
all_values
,
desc:
'Limit by minimum access level of authenticated user'
all_or_none_of
:extern_uid
,
:provider
all_or_none_of
:extern_uid
,
:provider
end
end
...
@@ -97,7 +98,7 @@ module API
...
@@ -97,7 +98,7 @@ module API
entity
=
current_user
&
.
admin?
?
Entities
::
UserWithAdmin
:
Entities
::
UserBasic
entity
=
current_user
&
.
admin?
?
Entities
::
UserWithAdmin
:
Entities
::
UserBasic
users
=
users
.
preload
(
:identities
,
:u2f_registrations
)
if
entity
==
Entities
::
UserWithAdmin
users
=
users
.
preload
(
:identities
,
:u2f_registrations
)
if
entity
==
Entities
::
UserWithAdmin
users
,
options
=
with_custom_attributes
(
users
,
with:
entity
)
users
,
options
=
with_custom_attributes
(
users
,
{
with:
entity
,
current_user:
current_user
}
)
present
paginate
(
users
),
options
present
paginate
(
users
),
options
end
end
...
@@ -114,7 +115,7 @@ module API
...
@@ -114,7 +115,7 @@ module API
user
=
User
.
find_by
(
id:
params
[
:id
])
user
=
User
.
find_by
(
id:
params
[
:id
])
not_found!
(
'User'
)
unless
user
&&
can?
(
current_user
,
:read_user
,
user
)
not_found!
(
'User'
)
unless
user
&&
can?
(
current_user
,
:read_user
,
user
)
opts
=
current_user
&
.
admin?
?
{
with:
Entities
::
UserWithAdmin
}
:
{
with:
Entities
::
U
ser
}
opts
=
{
with:
current_user
&
.
admin?
?
Entities
::
UserWithAdmin
:
Entities
::
User
,
current_user:
current_u
ser
}
user
,
opts
=
with_custom_attributes
(
user
,
opts
)
user
,
opts
=
with_custom_attributes
(
user
,
opts
)
present
user
,
opts
present
user
,
opts
...
@@ -140,7 +141,7 @@ module API
...
@@ -140,7 +141,7 @@ module API
user
=
::
Users
::
CreateService
.
new
(
current_user
,
params
).
execute
(
skip_authorization:
true
)
user
=
::
Users
::
CreateService
.
new
(
current_user
,
params
).
execute
(
skip_authorization:
true
)
if
user
.
persisted?
if
user
.
persisted?
present
user
,
with:
Entities
::
UserPublic
present
user
,
with:
Entities
::
UserPublic
,
current_user:
current_user
else
else
conflict!
(
'Email has already been taken'
)
if
User
conflict!
(
'Email has already been taken'
)
if
User
.
where
(
email:
user
.
email
)
.
where
(
email:
user
.
email
)
...
@@ -199,7 +200,7 @@ module API
...
@@ -199,7 +200,7 @@ module API
result
=
::
Users
::
UpdateService
.
new
(
current_user
,
user_params
.
except
(
:extern_uid
,
:provider
).
merge
(
user:
user
)).
execute
result
=
::
Users
::
UpdateService
.
new
(
current_user
,
user_params
.
except
(
:extern_uid
,
:provider
).
merge
(
user:
user
)).
execute
if
result
[
:status
]
==
:success
if
result
[
:status
]
==
:success
present
user
,
with:
Entities
::
UserPublic
present
user
,
with:
Entities
::
UserPublic
,
current_user:
current_user
else
else
render_validation_error!
(
user
)
render_validation_error!
(
user
)
end
end
...
@@ -546,7 +547,7 @@ module API
...
@@ -546,7 +547,7 @@ module API
Entities
::
UserPublic
Entities
::
UserPublic
end
end
present
current_user
,
with:
entity
present
current_user
,
with:
entity
,
current_user:
current_user
end
end
end
end
...
...
spec/controllers/users_controller_spec.rb
View file @
99011a61
...
@@ -2,6 +2,8 @@ require 'spec_helper'
...
@@ -2,6 +2,8 @@ require 'spec_helper'
describe
UsersController
do
describe
UsersController
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:private_user
)
{
create
(
:user
,
private_profile:
true
)
}
let
(
:public_user
)
{
create
(
:user
)
}
describe
'GET #show'
do
describe
'GET #show'
do
context
'with rendered views'
do
context
'with rendered views'
do
...
@@ -98,16 +100,47 @@ describe UsersController do
...
@@ -98,16 +100,47 @@ describe UsersController do
expect
(
assigns
(
:events
)).
to
be_empty
expect
(
assigns
(
:events
)).
to
be_empty
end
end
it
'hides events if the user has a private profile'
do
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
private_user
)
get
:show
,
username:
private_user
.
username
,
format: :json
expect
(
assigns
(
:events
)).
to
be_empty
end
end
end
end
end
describe
'GET #calendar'
do
describe
'GET #calendar'
do
it
'renders calendar'
do
context
'for user'
do
sign_in
(
user
)
let
(
:project
)
{
create
(
:project
)
}
before
do
sign_in
(
user
)
project
.
add_developer
(
user
)
end
context
'with public profile'
do
it
'renders calendar'
do
push_data
=
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
public_user
)
EventCreateService
.
new
.
push
(
project
,
public_user
,
push_data
)
get
:calendar
,
username:
public_user
.
username
,
format: :json
get
:calendar
,
username:
user
.
username
,
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
context
'with private profile'
do
it
'does not render calendar'
do
push_data
=
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
private_user
)
EventCreateService
.
new
.
push
(
project
,
private_user
,
push_data
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
get
:calendar
,
username:
private_user
.
username
,
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
end
context
'forked project'
do
context
'forked project'
do
...
@@ -150,9 +183,26 @@ describe UsersController do
...
@@ -150,9 +183,26 @@ describe UsersController do
expect
(
assigns
(
:calendar_date
)).
to
eq
(
Date
.
parse
(
'2014-07-31'
))
expect
(
assigns
(
:calendar_date
)).
to
eq
(
Date
.
parse
(
'2014-07-31'
))
end
end
it
'renders calendar_activities'
do
context
'for user'
do
get
:calendar_activities
,
username:
user
.
username
context
'with public profile'
do
expect
(
response
).
to
render_template
(
'calendar_activities'
)
it
'renders calendar_activities'
do
push_data
=
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
public_user
)
EventCreateService
.
new
.
push
(
project
,
public_user
,
push_data
)
get
:calendar_activities
,
username:
public_user
.
username
expect
(
assigns
[
:events
]).
not_to
be_empty
end
end
context
'with private profile'
do
it
'does not render calendar_activities'
do
push_data
=
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
private_user
)
EventCreateService
.
new
.
push
(
project
,
private_user
,
push_data
)
get
:calendar_activities
,
username:
private_user
.
username
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
end
end
end
...
...
spec/features/users/show_spec.rb
View file @
99011a61
...
@@ -3,15 +3,53 @@ require 'spec_helper'
...
@@ -3,15 +3,53 @@ require 'spec_helper'
describe
'User page'
do
describe
'User page'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
it
'shows all the tabs'
do
context
'with public profile'
do
visit
(
user_path
(
user
))
it
'shows all the tabs'
do
visit
(
user_path
(
user
))
page
.
within
'.nav-links'
do
expect
(
page
).
to
have_link
(
'Activity'
)
page
.
within
'.nav-links'
do
expect
(
page
).
to
have_link
(
'Groups'
)
expect
(
page
).
to
have_link
(
'Activity'
)
expect
(
page
).
to
have_link
(
'Contributed projects'
)
expect
(
page
).
to
have_link
(
'Groups'
)
expect
(
page
).
to
have_link
(
'Personal projects'
)
expect
(
page
).
to
have_link
(
'Contributed projects'
)
expect
(
page
).
to
have_link
(
'Snippets'
)
expect
(
page
).
to
have_link
(
'Personal projects'
)
expect
(
page
).
to
have_link
(
'Snippets'
)
end
end
it
'does not show private profile message'
do
visit
(
user_path
(
user
))
expect
(
page
).
not_to
have_content
(
"This user has a private profile"
)
end
end
context
'with private profile'
do
let
(
:user
)
{
create
(
:user
,
private_profile:
true
)
}
it
'shows no tab'
do
visit
(
user_path
(
user
))
expect
(
page
).
to
have_css
(
"div.profile-header"
)
expect
(
page
).
not_to
have_css
(
"ul.nav-links"
)
end
it
'shows private profile message'
do
visit
(
user_path
(
user
))
expect
(
page
).
to
have_content
(
"This user has a private profile"
)
end
it
'shows own tabs'
do
sign_in
(
user
)
visit
(
user_path
(
user
))
page
.
within
'.nav-links'
do
expect
(
page
).
to
have_link
(
'Activity'
)
expect
(
page
).
to
have_link
(
'Groups'
)
expect
(
page
).
to
have_link
(
'Contributed projects'
)
expect
(
page
).
to
have_link
(
'Personal projects'
)
expect
(
page
).
to
have_link
(
'Snippets'
)
end
end
end
end
end
...
...
spec/finders/user_recent_events_finder_spec.rb
View file @
99011a61
...
@@ -29,11 +29,22 @@ describe UserRecentEventsFinder do
...
@@ -29,11 +29,22 @@ describe UserRecentEventsFinder do
public_project
.
add_developer
(
current_user
)
public_project
.
add_developer
(
current_user
)
end
end
it
'returns all the events'
do
context
'when profile is public'
do
expect
(
finder
.
execute
).
to
include
(
private_event
,
internal_event
,
public_event
)
it
'returns all the events'
do
expect
(
finder
.
execute
).
to
include
(
private_event
,
internal_event
,
public_event
)
end
end
context
'when profile is private'
do
it
'returns no event'
do
allow
(
Ability
).
to
receive
(
:allowed?
).
and_call_original
allow
(
Ability
).
to
receive
(
:allowed?
).
with
(
current_user
,
:read_user_profile
,
project_owner
).
and_return
(
false
)
expect
(
finder
.
execute
).
to
be_empty
end
end
end
it
'does not include the events if the user cannot read cross project'
do
it
'does not include the events if the user cannot read cross project'
do
expect
(
Ability
).
to
receive
(
:allowed?
).
and_call_original
expect
(
Ability
).
to
receive
(
:allowed?
).
with
(
current_user
,
:read_cross_project
)
{
false
}
expect
(
Ability
).
to
receive
(
:allowed?
).
with
(
current_user
,
:read_cross_project
)
{
false
}
expect
(
finder
.
execute
).
to
be_empty
expect
(
finder
.
execute
).
to
be_empty
end
end
...
...
spec/helpers/users_helper_spec.rb
View file @
99011a61
...
@@ -25,8 +25,20 @@ describe UsersHelper do
...
@@ -25,8 +25,20 @@ describe UsersHelper do
allow
(
helper
).
to
receive
(
:can?
).
and_return
(
true
)
allow
(
helper
).
to
receive
(
:can?
).
and_return
(
true
)
end
end
it
'includes all the expected tabs'
do
context
'with public profile'
do
expect
(
tabs
).
to
include
(
:activity
,
:groups
,
:contributed
,
:projects
,
:snippets
)
it
'includes all the expected tabs'
do
expect
(
tabs
).
to
include
(
:activity
,
:groups
,
:contributed
,
:projects
,
:snippets
)
end
end
context
'with private profile'
do
before
do
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
:read_user_profile
,
nil
).
and_return
(
false
)
end
it
'is empty'
do
expect
(
tabs
).
to
be_empty
end
end
end
end
end
...
...
spec/requests/api/users_spec.rb
View file @
99011a61
...
@@ -11,6 +11,7 @@ describe API::Users do
...
@@ -11,6 +11,7 @@ describe API::Users do
let
(
:ldap_blocked_user
)
{
create
(
:omniauth_user
,
provider:
'ldapmain'
,
state:
'ldap_blocked'
)
}
let
(
:ldap_blocked_user
)
{
create
(
:omniauth_user
,
provider:
'ldapmain'
,
state:
'ldap_blocked'
)
}
let
(
:not_existing_user_id
)
{
(
User
.
maximum
(
'id'
)
||
0
)
+
10
}
let
(
:not_existing_user_id
)
{
(
User
.
maximum
(
'id'
)
||
0
)
+
10
}
let
(
:not_existing_pat_id
)
{
(
PersonalAccessToken
.
maximum
(
'id'
)
||
0
)
+
10
}
let
(
:not_existing_pat_id
)
{
(
PersonalAccessToken
.
maximum
(
'id'
)
||
0
)
+
10
}
let
(
:private_user
)
{
create
(
:user
,
private_profile:
true
)
}
describe
'GET /users'
do
describe
'GET /users'
do
context
"when unauthenticated"
do
context
"when unauthenticated"
do
...
@@ -254,6 +255,13 @@ describe API::Users do
...
@@ -254,6 +255,13 @@ describe API::Users do
expect
(
response
).
to
match_response_schema
(
'public_api/v4/user/admin'
)
expect
(
response
).
to
match_response_schema
(
'public_api/v4/user/admin'
)
expect
(
json_response
[
'is_admin'
]).
to
be
(
false
)
expect
(
json_response
[
'is_admin'
]).
to
be
(
false
)
end
end
it
"includes the `created_at` field for private users"
do
get
api
(
"/users/
#{
private_user
.
id
}
"
,
admin
)
expect
(
response
).
to
match_response_schema
(
'public_api/v4/user/admin'
)
expect
(
json_response
.
keys
).
to
include
'created_at'
end
end
end
context
'for an anonymous user'
do
context
'for an anonymous user'
do
...
@@ -272,6 +280,20 @@ describe API::Users do
...
@@ -272,6 +280,20 @@ describe API::Users do
expect
(
response
).
to
have_gitlab_http_status
(
404
)
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
it
"returns the `created_at` field for public users"
do
get
api
(
"/users/
#{
user
.
id
}
"
)
expect
(
response
).
to
match_response_schema
(
'public_api/v4/user/basic'
)
expect
(
json_response
.
keys
).
to
include
'created_at'
end
it
"does not return the `created_at` field for private users"
do
get
api
(
"/users/
#{
private_user
.
id
}
"
)
expect
(
response
).
to
match_response_schema
(
'public_api/v4/user/basic'
)
expect
(
json_response
.
keys
).
not_to
include
'created_at'
end
end
end
it
"returns a 404 error if user id not found"
do
it
"returns a 404 error if user id not found"
do
...
@@ -374,6 +396,18 @@ describe API::Users do
...
@@ -374,6 +396,18 @@ describe API::Users do
expect
(
new_user
.
recently_sent_password_reset?
).
to
eq
(
true
)
expect
(
new_user
.
recently_sent_password_reset?
).
to
eq
(
true
)
end
end
it
"creates user with private profile"
do
post
api
(
'/users'
,
admin
),
attributes_for
(
:user
,
private_profile:
true
)
expect
(
response
).
to
have_gitlab_http_status
(
201
)
user_id
=
json_response
[
'id'
]
new_user
=
User
.
find
(
user_id
)
expect
(
new_user
).
not_to
eq
(
nil
)
expect
(
new_user
.
private_profile?
).
to
eq
(
true
)
end
it
"does not create user with invalid email"
do
it
"does not create user with invalid email"
do
post
api
(
'/users'
,
admin
),
post
api
(
'/users'
,
admin
),
email:
'invalid email'
,
email:
'invalid email'
,
...
@@ -583,6 +617,13 @@ describe API::Users do
...
@@ -583,6 +617,13 @@ describe API::Users do
expect
(
user
.
reload
.
external?
).
to
be_truthy
expect
(
user
.
reload
.
external?
).
to
be_truthy
end
end
it
"updates private profile"
do
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
{
private_profile:
true
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
user
.
reload
.
private_profile
).
to
eq
(
true
)
end
it
"does not update admin status"
do
it
"does not update admin status"
do
put
api
(
"/users/
#{
admin_user
.
id
}
"
,
admin
),
{
can_create_group:
false
}
put
api
(
"/users/
#{
admin_user
.
id
}
"
,
admin
),
{
can_create_group:
false
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment