summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorImre <ifarkas@gitlab.com>2018-05-18 10:49:02 +0200
committerImre Farkas <ifarkas@gitlab.com>2018-06-06 10:12:52 +0200
commitc8f0e4b5da0c9d578035e74b524f5adcb80efcf6 (patch)
tree4e0a2624c77f42bebf1d06098074c61115828b2f
parentfe0ebf76c49e2512b211c5d43152275c536f7e3a (diff)
downloadgitlab-ce-c8f0e4b5da0c9d578035e74b524f5adcb80efcf6.tar.gz
Add Avatar API
-rw-r--r--changelogs/unreleased/45821-avatar_api.yml5
-rw-r--r--doc/api/avatar.md33
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/avatar.rb21
-rw-r--r--lib/api/entities.rb6
-rw-r--r--spec/requests/api/avatar_spec.rb106
6 files changed, 172 insertions, 0 deletions
diff --git a/changelogs/unreleased/45821-avatar_api.yml b/changelogs/unreleased/45821-avatar_api.yml
new file mode 100644
index 00000000000..e16b28c36a2
--- /dev/null
+++ b/changelogs/unreleased/45821-avatar_api.yml
@@ -0,0 +1,5 @@
+---
+title: Add Avatar API
+merge_request: 19121
+author: Imre Farkas
+type: added
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
new file mode 100644
index 00000000000..7faed893066
--- /dev/null
+++ b/doc/api/avatar.md
@@ -0,0 +1,33 @@
+# Avatar API
+
+> [Introduced][ce-19121] in GitLab 11.0
+
+## Get a single avatar URL
+
+Get a single avatar URL for a given email addres. If user with matching public
+email address is not found, results from external avatar services are returned.
+This endpoint can be accessed without authentication. In case public visibility
+is restricted, response will be `403 Forbidden` when unauthenticated.
+
+```
+GET /avatar?email=admin@example.com
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `email` | string | yes | Public email address of the user |
+| `size` | integer | no | Single pixel dimension (since images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server |
+
+```bash
+curl https://gitlab.example.com/api/v4/avatar?email=admin@example.com
+```
+
+Example response:
+
+```json
+{
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
+}
+```
+
+[ce-19121]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19121
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 7ea575a9661..e2ad3c5f4e3 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -83,6 +83,7 @@ module API
# Keep in alphabetical order
mount ::API::AccessRequests
mount ::API::Applications
+ mount ::API::Avatar
mount ::API::AwardEmoji
mount ::API::Badges
mount ::API::Boards
diff --git a/lib/api/avatar.rb b/lib/api/avatar.rb
new file mode 100644
index 00000000000..70219bc8ea0
--- /dev/null
+++ b/lib/api/avatar.rb
@@ -0,0 +1,21 @@
+module API
+ class Avatar < Grape::API
+ resource :avatar do
+ desc 'Return avatar url for a user' do
+ success Entities::Avatar
+ end
+ params do
+ requires :email, type: String, desc: 'Public email address of the user'
+ optional :size, type: Integer, desc: 'Single pixel dimension for Gravatar images'
+ end
+ get do
+ forbidden!('Unauthorized access') unless can?(current_user, :read_users_list)
+
+ user = User.find_by_public_email(params[:email])
+ user ||= User.new(email: params[:email])
+
+ present user, with: Entities::Avatar, size: params[:size]
+ end
+ end
+ end
+end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index c4537036a3a..b192f417014 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -692,6 +692,12 @@ module API
expose :notes, using: Entities::Note
end
+ class Avatar < Grape::Entity
+ expose :avatar_url do |avatarable, options|
+ avatarable.avatar_url(only_path: false, size: options[:size])
+ end
+ end
+
class AwardEmoji < Grape::Entity
expose :id
expose :name
diff --git a/spec/requests/api/avatar_spec.rb b/spec/requests/api/avatar_spec.rb
new file mode 100644
index 00000000000..26e0435a6d5
--- /dev/null
+++ b/spec/requests/api/avatar_spec.rb
@@ -0,0 +1,106 @@
+require 'spec_helper'
+
+describe API::Avatar do
+ let(:gravatar_service) { double('GravatarService') }
+
+ describe 'GET /avatar' do
+ context 'avatar uploaded to GitLab' do
+ context 'user with matching public email address' do
+ let(:user) { create(:user, :with_avatar, email: 'public@example.com', public_email: 'public@example.com') }
+
+ before do
+ user
+ end
+
+ it 'returns the avatar url' do
+ get api('/avatar'), { email: 'public@example.com' }
+
+ expect(response.status).to eq 200
+ expect(json_response['avatar_url']).to eql("#{::Settings.gitlab.base_url}#{user.avatar.local_url}")
+ end
+ end
+
+ context 'no user with matching public email address' do
+ before do
+ expect(GravatarService).to receive(:new).and_return(gravatar_service)
+ expect(gravatar_service).to(
+ receive(:execute)
+ .with('private@example.com', nil, 2, { username: nil })
+ .and_return('https://gravatar'))
+ end
+
+ it 'returns the avatar url from Gravatar' do
+ get api('/avatar'), { email: 'private@example.com' }
+
+ expect(response.status).to eq 200
+ expect(json_response['avatar_url']).to eq('https://gravatar')
+ end
+ end
+ end
+
+ context 'avatar uploaded to Gravatar' do
+ context 'user with matching public email address' do
+ let(:user) { create(:user, email: 'public@example.com', public_email: 'public@example.com') }
+
+ before do
+ user
+
+ expect(GravatarService).to receive(:new).and_return(gravatar_service)
+ expect(gravatar_service).to(
+ receive(:execute)
+ .with('public@example.com', nil, 2, { username: user.username })
+ .and_return('https://gravatar'))
+ end
+
+ it 'returns the avatar url from Gravatar' do
+ get api('/avatar'), { email: 'public@example.com' }
+
+ expect(response.status).to eq 200
+ expect(json_response['avatar_url']).to eq('https://gravatar')
+ end
+ end
+
+ context 'no user with matching public email address' do
+ before do
+ expect(GravatarService).to receive(:new).and_return(gravatar_service)
+ expect(gravatar_service).to(
+ receive(:execute)
+ .with('private@example.com', nil, 2, { username: nil })
+ .and_return('https://gravatar'))
+ end
+
+ it 'returns the avatar url from Gravatar' do
+ get api('/avatar'), { email: 'private@example.com' }
+
+ expect(response.status).to eq 200
+ expect(json_response['avatar_url']).to eq('https://gravatar')
+ end
+ end
+
+ context 'public visibility level restricted' do
+ let(:user) { create(:user, :with_avatar, email: 'public@example.com', public_email: 'public@example.com') }
+
+ before do
+ user
+
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
+ end
+
+ context 'when authenticated' do
+ it 'returns the avatar url' do
+ get api('/avatar', user), { email: 'public@example.com' }
+
+ expect(response.status).to eq 200
+ expect(json_response['avatar_url']).to eql("#{::Settings.gitlab.base_url}#{user.avatar.local_url}")
+ end
+ end
+
+ context 'when unauthenticated' do
+ it_behaves_like '403 response' do
+ let(:request) { get api('/avatar'), { email: 'public@example.com' } }
+ end
+ end
+ end
+ end
+ end
+end