Commit ae564c97 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

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: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent d5b0f29c
...@@ -37,13 +37,9 @@ ...@@ -37,13 +37,9 @@
projectUserFormatResult: (user) -> projectUserFormatResult: (user) ->
if user.avatar_url if user.avatar_url
avatar = gon.relative_url_root + user.avatar_url avatar = user.avatar_url
else if gon.gravatar_enabled
avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24')
else else
avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" avatar = gon.default_avatar_url
if user.id == '' if user.id == ''
avatarMarkup = '' avatarMarkup = ''
......
$ -> $ ->
userFormatResult = (user) -> userFormatResult = (user) ->
if user.avatar_url if user.avatar_url
avatar = gon.relative_url_root + user.avatar_url avatar = user.avatar_url
else if gon.gravatar_enabled
avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24')
else else
avatar = gon.relative_url_root + "#{image_path('no_avatar.png')}" avatar = gon.default_avatar_url
"<div class='user-result'> "<div class='user-result'>
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div> <div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
......
...@@ -164,9 +164,8 @@ class ApplicationController < ActionController::Base ...@@ -164,9 +164,8 @@ class ApplicationController < ActionController::Base
def add_gon_variables def add_gon_variables
gon.default_issues_tracker = Project.issues_tracker.default_value gon.default_issues_tracker = Project.issues_tracker.default_value
gon.api_version = API::API.version gon.api_version = API::API.version
gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.gravatar_enabled = Gitlab.config.gravatar.enabled gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
if current_user if current_user
gon.current_user_id = current_user.id gon.current_user_id = current_user.id
......
...@@ -60,23 +60,21 @@ module ApplicationHelper ...@@ -60,23 +60,21 @@ module ApplicationHelper
def avatar_icon(user_email = '', size = nil) def avatar_icon(user_email = '', size = nil)
user = User.find_by(email: user_email) user = User.find_by(email: user_email)
if user && user.avatar.present?
user.avatar.url if user
user.avatar_url(size) || default_avatar
else else
gravatar_icon(user_email, size) gravatar_icon(user_email, size)
end end
end end
def gravatar_icon(user_email = '', size = nil) def gravatar_icon(user_email = '', size = nil)
size = 40 if size.nil? || size <= 0 GravatarService.new.execute(user_email, size) ||
default_avatar
end
if !Gitlab.config.gravatar.enabled || user_email.blank? def default_avatar
image_path('no_avatar.png') image_path('no_avatar.png')
else
gravatar_url = request.ssl? || gitlab_config.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
user_email.strip!
sprintf gravatar_url, hash: Digest::MD5.hexdigest(user_email.downcase), size: size, email: user_email
end
end end
def last_commit(project) def last_commit(project)
......
...@@ -482,4 +482,12 @@ class User < ActiveRecord::Base ...@@ -482,4 +482,12 @@ class User < ActiveRecord::Base
def public_profile? def public_profile?
authorized_projects.public_only.any? authorized_projects.public_only.any?
end end
def avatar_url(size = nil)
if avatar.present?
URI::join(Gitlab.config.gitlab.url, avatar.url).to_s
else
GravatarService.new.execute(email)
end
end
end end
module API module API
module Entities module Entities
class User < Grape::Entity class UserSafe < Grape::Entity
expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, :website_url, expose :name, :username
:theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider end
expose :is_admin?, as: :is_admin
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
expose :avatar_url do |user, options| class UserBasic < UserSafe
if user.avatar.present? expose :id, :state, :avatar_url
user.avatar.url
end
end
end end
class UserSafe < Grape::Entity class User < UserBasic
expose :name, :username expose :created_at
expose :is_admin?, as: :is_admin
expose :bio, :skype, :linkedin, :twitter, :website_url
end end
class UserBasic < Grape::Entity class UserFull < User
expose :id, :username, :email, :name, :state, :created_at expose :email
expose :theme_id, :color_scheme_id, :extern_uid, :provider
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
end end
class UserLogin < User class UserLogin < UserFull
expose :private_token expose :private_token
end end
......
...@@ -59,4 +59,3 @@ module API ...@@ -59,4 +59,3 @@ module API
end end
end end
end end
...@@ -209,7 +209,7 @@ module API ...@@ -209,7 +209,7 @@ module API
@users = User.where(id: user_project.team.users.map(&:id)) @users = User.where(id: user_project.team.users.map(&:id))
@users = @users.search(params[:search]) if params[:search].present? @users = @users.search(params[:search]) if params[:search].present?
@users = paginate @users @users = paginate @users
present @users, with: Entities::User present @users, with: Entities::UserBasic
end end
# Get a project labels # Get a project labels
......
...@@ -13,7 +13,12 @@ module API ...@@ -13,7 +13,12 @@ module API
@users = @users.active if params[:active].present? @users = @users.active if params[:active].present?
@users = @users.search(params[:search]) if params[:search].present? @users = @users.search(params[:search]) if params[:search].present?
@users = paginate @users @users = paginate @users
present @users, with: Entities::User
if current_user.is_admin?
present @users, with: Entities::UserFull
else
present @users, with: Entities::UserBasic
end
end end
# Get a single user # Get a single user
...@@ -24,7 +29,12 @@ module API ...@@ -24,7 +29,12 @@ module API
# GET /users/:id # GET /users/:id
get ":id" do get ":id" do
@user = User.find(params[:id]) @user = User.find(params[:id])
present @user, with: Entities::User
if current_user.is_admin?
present @user, with: Entities::UserFull
else
present @user, with: Entities::UserBasic
end
end end
# Create user. Available only for admin # Create user. Available only for admin
...@@ -53,7 +63,7 @@ module API ...@@ -53,7 +63,7 @@ module API
admin = attrs.delete(:admin) admin = attrs.delete(:admin)
user.admin = admin unless admin.nil? user.admin = admin unless admin.nil?
if user.save if user.save
present user, with: Entities::User present user, with: Entities::UserFull
else else
not_found! not_found!
end end
...@@ -87,7 +97,7 @@ module API ...@@ -87,7 +97,7 @@ module API
admin = attrs.delete(:admin) admin = attrs.delete(:admin)
user.admin = admin unless admin.nil? user.admin = admin unless admin.nil?
if user.update_attributes(attrs, as: :admin) if user.update_attributes(attrs, as: :admin)
present user, with: Entities::User present user, with: Entities::UserFull
else else
not_found! not_found!
end end
......
...@@ -20,7 +20,7 @@ describe API::API, api: true do ...@@ -20,7 +20,7 @@ describe API::API, api: true do
get api("/users", user) get api("/users", user)
response.status.should == 200 response.status.should == 200
json_response.should be_an Array json_response.should be_an Array
json_response.first['email'].should == user.email json_response.first['username'].should == user.username
end end
end end
end end
...@@ -29,7 +29,7 @@ describe API::API, api: true do ...@@ -29,7 +29,7 @@ describe API::API, api: true do
it "should return a user by id" do it "should return a user by id" do
get api("/users/#{user.id}", user) get api("/users/#{user.id}", user)
response.status.should == 200 response.status.should == 200
json_response['email'].should == user.email json_response['username'].should == user.username
end end
it "should return a 401 if unauthenticated" do it "should return a 401 if unauthenticated" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment