Commit ae564c97d48bf728745c57720734cb40378fd90f
1 parent
d5b0f29c
Exists in
spb-stable
and in
2 other branches
Dont expose user email via API
To prevent leaking of users info we reduce amount of user information retrieved via API for normal users. What user can get via API: * if not admin: only id, state, name, username and avatar_url * if admin: all user information * about himself: all informaion Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Showing
10 changed files
with
53 additions
and
48 deletions
Show diff stats
app/assets/javascripts/project_users_select.js.coffee
... | ... | @@ -37,13 +37,9 @@ |
37 | 37 | |
38 | 38 | projectUserFormatResult: (user) -> |
39 | 39 | if user.avatar_url |
40 | - avatar = gon.relative_url_root + user.avatar_url | |
41 | - else if gon.gravatar_enabled | |
42 | - avatar = gon.gravatar_url | |
43 | - avatar = avatar.replace('%{hash}', md5(user.email)) | |
44 | - avatar = avatar.replace('%{size}', '24') | |
40 | + avatar = user.avatar_url | |
45 | 41 | else |
46 | - avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" | |
42 | + avatar = gon.default_avatar_url | |
47 | 43 | |
48 | 44 | if user.id == '' |
49 | 45 | avatarMarkup = '' | ... | ... |
app/assets/javascripts/users_select.js.coffee
1 | 1 | $ -> |
2 | 2 | userFormatResult = (user) -> |
3 | 3 | if user.avatar_url |
4 | - avatar = gon.relative_url_root + user.avatar_url | |
5 | - else if gon.gravatar_enabled | |
6 | - avatar = gon.gravatar_url | |
7 | - avatar = avatar.replace('%{hash}', md5(user.email)) | |
8 | - avatar = avatar.replace('%{size}', '24') | |
4 | + avatar = user.avatar_url | |
9 | 5 | else |
10 | - avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" | |
6 | + avatar = gon.default_avatar_url | |
11 | 7 | |
12 | 8 | "<div class='user-result'> |
13 | 9 | <div class='user-image'><img class='avatar s24' src='#{avatar}'></div> | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -164,9 +164,8 @@ class ApplicationController < ActionController::Base |
164 | 164 | def add_gon_variables |
165 | 165 | gon.default_issues_tracker = Project.issues_tracker.default_value |
166 | 166 | gon.api_version = API::API.version |
167 | - gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url | |
168 | 167 | gon.relative_url_root = Gitlab.config.gitlab.relative_url_root |
169 | - gon.gravatar_enabled = Gitlab.config.gravatar.enabled | |
168 | + gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s | |
170 | 169 | |
171 | 170 | if current_user |
172 | 171 | gon.current_user_id = current_user.id | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -60,23 +60,21 @@ module ApplicationHelper |
60 | 60 | |
61 | 61 | def avatar_icon(user_email = '', size = nil) |
62 | 62 | user = User.find_by(email: user_email) |
63 | - if user && user.avatar.present? | |
64 | - user.avatar.url | |
63 | + | |
64 | + if user | |
65 | + user.avatar_url(size) || default_avatar | |
65 | 66 | else |
66 | 67 | gravatar_icon(user_email, size) |
67 | 68 | end |
68 | 69 | end |
69 | 70 | |
70 | 71 | def gravatar_icon(user_email = '', size = nil) |
71 | - size = 40 if size.nil? || size <= 0 | |
72 | + GravatarService.new.execute(user_email, size) || | |
73 | + default_avatar | |
74 | + end | |
72 | 75 | |
73 | - if !Gitlab.config.gravatar.enabled || user_email.blank? | |
74 | - image_path('no_avatar.png') | |
75 | - else | |
76 | - gravatar_url = request.ssl? || gitlab_config.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url | |
77 | - user_email.strip! | |
78 | - sprintf gravatar_url, hash: Digest::MD5.hexdigest(user_email.downcase), size: size, email: user_email | |
79 | - end | |
76 | + def default_avatar | |
77 | + image_path('no_avatar.png') | |
80 | 78 | end |
81 | 79 | |
82 | 80 | def last_commit(project) | ... | ... |
app/models/user.rb
... | ... | @@ -482,4 +482,12 @@ class User < ActiveRecord::Base |
482 | 482 | def public_profile? |
483 | 483 | authorized_projects.public_only.any? |
484 | 484 | end |
485 | + | |
486 | + def avatar_url(size = nil) | |
487 | + if avatar.present? | |
488 | + URI::join(Gitlab.config.gitlab.url, avatar.url).to_s | |
489 | + else | |
490 | + GravatarService.new.execute(email) | |
491 | + end | |
492 | + end | |
485 | 493 | end | ... | ... |
lib/api/entities.rb
1 | 1 | module API |
2 | 2 | module Entities |
3 | - class User < Grape::Entity | |
4 | - expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, :website_url, | |
5 | - :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider | |
6 | - expose :is_admin?, as: :is_admin | |
7 | - expose :can_create_group?, as: :can_create_group | |
8 | - expose :can_create_project?, as: :can_create_project | |
3 | + class UserSafe < Grape::Entity | |
4 | + expose :name, :username | |
5 | + end | |
9 | 6 | |
10 | - expose :avatar_url do |user, options| | |
11 | - if user.avatar.present? | |
12 | - user.avatar.url | |
13 | - end | |
14 | - end | |
7 | + class UserBasic < UserSafe | |
8 | + expose :id, :state, :avatar_url | |
15 | 9 | end |
16 | 10 | |
17 | - class UserSafe < Grape::Entity | |
18 | - expose :name, :username | |
11 | + class User < UserBasic | |
12 | + expose :created_at | |
13 | + expose :is_admin?, as: :is_admin | |
14 | + expose :bio, :skype, :linkedin, :twitter, :website_url | |
19 | 15 | end |
20 | 16 | |
21 | - class UserBasic < Grape::Entity | |
22 | - expose :id, :username, :email, :name, :state, :created_at | |
17 | + class UserFull < User | |
18 | + expose :email | |
19 | + expose :theme_id, :color_scheme_id, :extern_uid, :provider | |
20 | + expose :can_create_group?, as: :can_create_group | |
21 | + expose :can_create_project?, as: :can_create_project | |
23 | 22 | end |
24 | 23 | |
25 | - class UserLogin < User | |
24 | + class UserLogin < UserFull | |
26 | 25 | expose :private_token |
27 | 26 | end |
28 | 27 | ... | ... |
lib/api/internal.rb
lib/api/projects.rb
... | ... | @@ -209,7 +209,7 @@ module API |
209 | 209 | @users = User.where(id: user_project.team.users.map(&:id)) |
210 | 210 | @users = @users.search(params[:search]) if params[:search].present? |
211 | 211 | @users = paginate @users |
212 | - present @users, with: Entities::User | |
212 | + present @users, with: Entities::UserBasic | |
213 | 213 | end |
214 | 214 | |
215 | 215 | # Get a project labels | ... | ... |
lib/api/users.rb
... | ... | @@ -13,7 +13,12 @@ module API |
13 | 13 | @users = @users.active if params[:active].present? |
14 | 14 | @users = @users.search(params[:search]) if params[:search].present? |
15 | 15 | @users = paginate @users |
16 | - present @users, with: Entities::User | |
16 | + | |
17 | + if current_user.is_admin? | |
18 | + present @users, with: Entities::UserFull | |
19 | + else | |
20 | + present @users, with: Entities::UserBasic | |
21 | + end | |
17 | 22 | end |
18 | 23 | |
19 | 24 | # Get a single user |
... | ... | @@ -24,7 +29,12 @@ module API |
24 | 29 | # GET /users/:id |
25 | 30 | get ":id" do |
26 | 31 | @user = User.find(params[:id]) |
27 | - present @user, with: Entities::User | |
32 | + | |
33 | + if current_user.is_admin? | |
34 | + present @user, with: Entities::UserFull | |
35 | + else | |
36 | + present @user, with: Entities::UserBasic | |
37 | + end | |
28 | 38 | end |
29 | 39 | |
30 | 40 | # Create user. Available only for admin |
... | ... | @@ -53,7 +63,7 @@ module API |
53 | 63 | admin = attrs.delete(:admin) |
54 | 64 | user.admin = admin unless admin.nil? |
55 | 65 | if user.save |
56 | - present user, with: Entities::User | |
66 | + present user, with: Entities::UserFull | |
57 | 67 | else |
58 | 68 | not_found! |
59 | 69 | end |
... | ... | @@ -87,7 +97,7 @@ module API |
87 | 97 | admin = attrs.delete(:admin) |
88 | 98 | user.admin = admin unless admin.nil? |
89 | 99 | if user.update_attributes(attrs, as: :admin) |
90 | - present user, with: Entities::User | |
100 | + present user, with: Entities::UserFull | |
91 | 101 | else |
92 | 102 | not_found! |
93 | 103 | end | ... | ... |
spec/requests/api/users_spec.rb
... | ... | @@ -20,7 +20,7 @@ describe API::API, api: true do |
20 | 20 | get api("/users", user) |
21 | 21 | response.status.should == 200 |
22 | 22 | json_response.should be_an Array |
23 | - json_response.first['email'].should == user.email | |
23 | + json_response.first['username'].should == user.username | |
24 | 24 | end |
25 | 25 | end |
26 | 26 | end |
... | ... | @@ -29,7 +29,7 @@ describe API::API, api: true do |
29 | 29 | it "should return a user by id" do |
30 | 30 | get api("/users/#{user.id}", user) |
31 | 31 | response.status.should == 200 |
32 | - json_response['email'].should == user.email | |
32 | + json_response['username'].should == user.username | |
33 | 33 | end |
34 | 34 | |
35 | 35 | it "should return a 401 if unauthenticated" do | ... | ... |