Commit 0be55733 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'grapify-users-api' into 'master'

Grapify the users API

Certain endpoints return different entities based on which user issues the request. Right now, I am not aware how to specify multiple entities as part of the description block of the endpoint. @rymai Do you know something about that.

## What are the relevant issue numbers?

Related to #22928

See merge request !7147
parents 5018bdcd 4cb3c0b4
...@@ -369,24 +369,24 @@ Parameters: ...@@ -369,24 +369,24 @@ Parameters:
Get a list of a specified user's SSH keys. Available only for admin Get a list of a specified user's SSH keys. Available only for admin
``` ```
GET /users/:uid/keys GET /users/:id/keys
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
## Single SSH key ## Single SSH key
Get a single key. Get a single key.
``` ```
GET /user/keys/:id GET /user/keys/:key_id
``` ```
Parameters: Parameters:
- `id` (required) - The ID of an SSH key - `key_id` (required) - The ID of an SSH key
```json ```json
{ {
...@@ -458,25 +458,25 @@ This is an idempotent function and calling it on a key that is already deleted ...@@ -458,25 +458,25 @@ This is an idempotent function and calling it on a key that is already deleted
or not available results in `200 OK`. or not available results in `200 OK`.
``` ```
DELETE /user/keys/:id DELETE /user/keys/:key_id
``` ```
Parameters: Parameters:
- `id` (required) - SSH key ID - `key_id` (required) - SSH key ID
## Delete SSH key for given user ## Delete SSH key for given user
Deletes key owned by a specified user. Available only for admin. Deletes key owned by a specified user. Available only for admin.
``` ```
DELETE /users/:uid/keys/:id DELETE /users/:id/keys/:key_id
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
- `id` (required) - SSH key ID - `key_id` (required) - SSH key ID
Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found.
...@@ -510,24 +510,24 @@ Parameters: ...@@ -510,24 +510,24 @@ Parameters:
Get a list of a specified user's emails. Available only for admin Get a list of a specified user's emails. Available only for admin
``` ```
GET /users/:uid/emails GET /users/:id/emails
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
## Single email ## Single email
Get a single email. Get a single email.
``` ```
GET /user/emails/:id GET /user/emails/:email_id
``` ```
Parameters: Parameters:
- `id` (required) - email ID - `email_id` (required) - email ID
```json ```json
{ {
...@@ -590,25 +590,25 @@ This is an idempotent function and calling it on a email that is already deleted ...@@ -590,25 +590,25 @@ This is an idempotent function and calling it on a email that is already deleted
or not available results in `200 OK`. or not available results in `200 OK`.
``` ```
DELETE /user/emails/:id DELETE /user/emails/:email_id
``` ```
Parameters: Parameters:
- `id` (required) - email ID - `email_id` (required) - email ID
## Delete email for given user ## Delete email for given user
Deletes email owned by a specified user. Available only for admin. Deletes email owned by a specified user. Available only for admin.
``` ```
DELETE /users/:uid/emails/:id DELETE /users/:id/emails/:email_id
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
- `id` (required) - email ID - `email_id` (required) - email ID
Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found. Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found.
...@@ -617,12 +617,12 @@ Will return `200 OK` on success, or `404 Not found` if either user or email cann ...@@ -617,12 +617,12 @@ Will return `200 OK` on success, or `404 Not found` if either user or email cann
Blocks the specified user. Available only for admin. Blocks the specified user. Available only for admin.
``` ```
PUT /users/:uid/block PUT /users/:id/block
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to block an already blocked user by LDAP synchronization. `403 Forbidden` when trying to block an already blocked user by LDAP synchronization.
...@@ -632,12 +632,12 @@ Will return `200 OK` on success, `404 User Not Found` is user cannot be found or ...@@ -632,12 +632,12 @@ Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
Unblocks the specified user. Available only for admin. Unblocks the specified user. Available only for admin.
``` ```
PUT /users/:uid/unblock PUT /users/:id/unblock
``` ```
Parameters: Parameters:
- `uid` (required) - id of specified user - `id` (required) - id of specified user
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization. `403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
......
...@@ -4,89 +4,93 @@ module API ...@@ -4,89 +4,93 @@ module API
before { authenticate! } before { authenticate! }
resource :users, requirements: { uid: /[0-9]*/, id: /[0-9]*/ } do resource :users, requirements: { uid: /[0-9]*/, id: /[0-9]*/ } do
# Get a users list helpers do
# params :optional_attributes do
# Example Request: optional :skype, type: String, desc: 'The Skype username'
# GET /users optional :linkedin, type: String, desc: 'The LinkedIn username'
# GET /users?search=Admin optional :twitter, type: String, desc: 'The Twitter username'
# GET /users?username=root optional :website_url, type: String, desc: 'The website of the user'
# GET /users?active=true optional :organization, type: String, desc: 'The organization of the user'
# GET /users?external=true optional :projects_limit, type: Integer, desc: 'The number of projects a user can create'
# GET /users?blocked=true optional :extern_uid, type: Integer, desc: 'The external authentication provider UID'
optional :provider, type: String, desc: 'The external provider'
optional :bio, type: String, desc: 'The biography of the user'
optional :location, type: String, desc: 'The location of the user'
optional :admin, type: Boolean, desc: 'Flag indicating the user is an administrator'
optional :can_create_group, type: Boolean, desc: 'Flag indicating the user can create groups'
optional :confirm, type: Boolean, desc: 'Flag indicating the account needs to be confirmed'
optional :external, type: Boolean, desc: 'Flag indicating the user is an external user'
all_or_none_of :extern_uid, :provider
end
end
desc 'Get the list of users' do
success Entities::UserBasic
end
params do
optional :username, type: String, desc: 'Get a single user with a specific username'
optional :search, type: String, desc: 'Search for a username'
optional :active, type: Boolean, default: false, desc: 'Filters only active users'
optional :external, type: Boolean, default: false, desc: 'Filters only external users'
optional :blocked, type: Boolean, default: false, desc: 'Filters only blocked users'
end
get do get do
unless can?(current_user, :read_users_list, nil) unless can?(current_user, :read_users_list, nil)
render_api_error!("Not authorized.", 403) render_api_error!("Not authorized.", 403)
end end
if params[:username].present? if params[:username].present?
@users = User.where(username: params[:username]) users = User.where(username: params[:username])
else else
@users = User.all users = User.all
@users = @users.active if to_boolean(params[:active]) users = users.active if params[:active]
@users = @users.search(params[:search]) if params[:search].present? users = users.search(params[:search]) if params[:search].present?
@users = @users.blocked if to_boolean(params[:blocked]) users = users.blocked if params[:blocked]
@users = @users.external if to_boolean(params[:external]) && current_user.is_admin? users = users.external if params[:external] && current_user.is_admin?
@users = paginate @users
end end
if current_user.is_admin? entity = current_user.is_admin? ? Entities::UserFull : Entities::UserBasic
present @users, with: Entities::UserFull present paginate(users), with: entity
else
present @users, with: Entities::UserBasic
end
end end
# Get a single user desc 'Get a single user' do
# success Entities::UserBasic
# Parameters: end
# id (required) - The ID of a user params do
# Example Request: requires :id, type: Integer, desc: 'The ID of the user'
# GET /users/:id end
get ":id" do get ":id" do
@user = User.find(params[:id]) user = User.find_by(id: params[:id])
not_found!('User') unless user
if current_user && current_user.is_admin? if current_user && current_user.is_admin?
present @user, with: Entities::UserFull present user, with: Entities::UserFull
elsif can?(current_user, :read_user, @user) elsif can?(current_user, :read_user, user)
present @user, with: Entities::User present user, with: Entities::User
else else
render_api_error!("User not found.", 404) render_api_error!("User not found.", 404)
end end
end end
# Create user. Available only for admin desc 'Create a user. Available only for admins.' do
# success Entities::UserFull
# Parameters: end
# email (required) - Email params do
# password (required) - Password requires :email, type: String, desc: 'The email of the user'
# name (required) - Name requires :password, type: String, desc: 'The password of the new user'
# username (required) - Name requires :name, type: String, desc: 'The name of the user'
# skype - Skype ID requires :username, type: String, desc: 'The username of the user'
# linkedin - Linkedin use :optional_attributes
# twitter - Twitter account end
# website_url - Website url
# organization - Organization
# projects_limit - Number of projects user can create
# extern_uid - External authentication provider UID
# provider - External provider
# bio - Bio
# location - Location of the user
# admin - User is admin - true or false (default)
# can_create_group - User can create groups - true or false
# confirm - Require user confirmation - true (default) or false
# external - Flags the user as external - true or false(default)
# Example Request:
# POST /users
post do post do
authenticated_as_admin! authenticated_as_admin!
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :confirm, :external, :organization] # Filter out params which are used later
admin = attrs.delete(:admin) identity_attrs = params.slice(:provider, :extern_uid)
confirm = !(attrs.delete(:confirm) =~ /(false|f|no|0)$/i) confirm = params.delete(:confirm)
user = User.build_user(attrs)
user.admin = admin unless admin.nil? user = User.build_user(declared_params(include_missing: false))
user.skip_confirmation! unless confirm user.skip_confirmation! unless confirm
identity_attrs = attributes_for_keys [:provider, :extern_uid]
if identity_attrs.any? if identity_attrs.any?
user.identities.build(identity_attrs) user.identities.build(identity_attrs)
...@@ -107,46 +111,40 @@ module API ...@@ -107,46 +111,40 @@ module API
end end
end end
# Update user. Available only for admin desc 'Update a user. Available only for admins.' do
# success Entities::UserFull
# Parameters: end
# email - Email params do
# name - Name requires :id, type: Integer, desc: 'The ID of the user'
# password - Password optional :email, type: String, desc: 'The email of the user'
# skype - Skype ID optional :password, type: String, desc: 'The password of the new user'
# linkedin - Linkedin optional :name, type: String, desc: 'The name of the user'
# twitter - Twitter account optional :username, type: String, desc: 'The username of the user'
# website_url - Website url use :optional_attributes
# organization - Organization at_least_one_of :email, :password, :name, :username, :skype, :linkedin,
# projects_limit - Limit projects each user can create :twitter, :website_url, :organization, :projects_limit,
# bio - Bio :extern_uid, :provider, :bio, :location, :admin,
# location - Location of the user :can_create_group, :confirm, :external
# admin - User is admin - true or false (default) end
# can_create_group - User can create groups - true or false
# external - Flags the user as external - true or false(default)
# Example Request:
# PUT /users/:id
put ":id" do put ":id" do
authenticated_as_admin! authenticated_as_admin!
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :external, :organization] user = User.find_by(id: params.delete(:id))
user = User.find(params[:id])
not_found!('User') unless user not_found!('User') unless user
admin = attrs.delete(:admin) conflict!('Email has already been taken') if params[:email] &&
user.admin = admin unless admin.nil? User.where(email: params[:email]).
conflict!('Email has already been taken') if attrs[:email] &&
User.where(email: attrs[:email]).
where.not(id: user.id).count > 0 where.not(id: user.id).count > 0
conflict!('Username has already been taken') if attrs[:username] && conflict!('Username has already been taken') if params[:username] &&
User.where(username: attrs[:username]). User.where(username: params[:username]).
where.not(id: user.id).count > 0 where.not(id: user.id).count > 0
identity_attrs = attributes_for_keys [:provider, :extern_uid] identity_attrs = params.slice(:provider, :extern_uid)
if identity_attrs.any? if identity_attrs.any?
identity = user.identities.find_by(provider: identity_attrs[:provider]) identity = user.identities.find_by(provider: identity_attrs[:provider])
if identity if identity
identity.update_attributes(identity_attrs) identity.update_attributes(identity_attrs)
else else
...@@ -155,28 +153,33 @@ module API ...@@ -155,28 +153,33 @@ module API
end end
end end
if user.update_attributes(attrs) # Delete already handled parameters
params.delete(:extern_uid)
params.delete(:provider)
if user.update_attributes(declared_params(include_missing: false))
present user, with: Entities::UserFull present user, with: Entities::UserFull
else else
render_validation_error!(user) render_validation_error!(user)
end end
end end
# Add ssh key to a specified user. Only available to admin users. desc 'Add an SSH key to a specified user. Available only for admins.' do
# success Entities::SSHKey
# Parameters: end
# id (required) - The ID of a user params do
# key (required) - New SSH Key requires :id, type: Integer, desc: 'The ID of the user'
# title (required) - New SSH Key's title requires :key, type: String, desc: 'The new SSH key'
# Example Request: requires :title, type: String, desc: 'The title of the new SSH key'
# POST /users/:id/keys end
post ":id/keys" do post ":id/keys" do
authenticated_as_admin! authenticated_as_admin!
required_attributes! [:title, :key]
user = User.find(params[:id]) user = User.find_by(id: params.delete(:id))
attrs = attributes_for_keys [:title, :key] not_found!('User') unless user
key = user.keys.new attrs
key = user.keys.new(declared_params(include_missing: false))
if key.save if key.save
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
else else
...@@ -184,55 +187,55 @@ module API ...@@ -184,55 +187,55 @@ module API
end end
end end
# Get ssh keys of a specified user. Only available to admin users. desc 'Get the SSH keys of a specified user. Available only for admins.' do
# success Entities::SSHKey
# Parameters: end
# uid (required) - The ID of a user params do
# Example Request: requires :id, type: Integer, desc: 'The ID of the user'
# GET /users/:uid/keys end
get ':uid/keys' do get ':id/keys' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:uid])
user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
present user.keys, with: Entities::SSHKey present user.keys, with: Entities::SSHKey
end end
# Delete existing ssh key of a specified user. Only available to admin desc 'Delete an existing SSH key from a specified user. Available only for admins.' do
# users. success Entities::SSHKey
# end
# Parameters: params do
# uid (required) - The ID of a user requires :id, type: Integer, desc: 'The ID of the user'
# id (required) - SSH Key ID requires :key_id, type: Integer, desc: 'The ID of the SSH key'
# Example Request: end
# DELETE /users/:uid/keys/:id delete ':id/keys/:key_id' do
delete ':uid/keys/:id' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:uid])
user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
begin key = user.keys.find_by(id: params[:key_id])
key = user.keys.find params[:id] not_found!('Key') unless key
key.destroy
rescue ActiveRecord::RecordNotFound present key.destroy, with: Entities::SSHKey
not_found!('Key')
end
end end
# Add email to a specified user. Only available to admin users. desc 'Add an email address to a specified user. Available only for admins.' do
# success Entities::Email
# Parameters: end
# id (required) - The ID of a user params do
# email (required) - Email address requires :id, type: Integer, desc: 'The ID of the user'
# Example Request: requires :email, type: String, desc: 'The email of the user'
# POST /users/:id/emails end
post ":id/emails" do post ":id/emails" do
authenticated_as_admin! authenticated_as_admin!
required_attributes! [:email]
user = User.find(params[:id]) user = User.find_by(id: params.delete(:id))
attrs = attributes_for_keys [:email] not_found!('User') unless user
email = user.emails.new attrs
email = user.emails.new(declared_params(include_missing: false))
if email.save if email.save
NotificationService.new.new_email(email) NotificationService.new.new_email(email)
present email, with: Entities::Email present email, with: Entities::Email
...@@ -241,98 +244,91 @@ module API ...@@ -241,98 +244,91 @@ module API
end end
end end
# Get emails of a specified user. Only available to admin users. desc 'Get the emails addresses of a specified user. Available only for admins.' do
# success Entities::Email
# Parameters: end
# uid (required) - The ID of a user params do
# Example Request: requires :id, type: Integer, desc: 'The ID of the user'
# GET /users/:uid/emails end
get ':uid/emails' do get ':id/emails' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:uid]) user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
present user.emails, with: Entities::Email present user.emails, with: Entities::Email
end end
# Delete existing email of a specified user. Only available to admin desc 'Delete an email address of a specified user. Available only for admins.' do
# users. success Entities::Email
# end
# Parameters: params do
# uid (required) - The ID of a user requires :id, type: Integer, desc: 'The ID of the user'
# id (required) - Email ID requires :email_id, type: Integer, desc: 'The ID of the email'
# Example Request: end
# DELETE /users/:uid/emails/:id delete ':id/emails/:email_id' do
delete ':uid/emails/:id' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:uid]) user = User.find_by(id: params[:id])
not_found!('User') unless user not_found!('User') unless user
begin email = user.emails.find_by(id: params[:email_id])
email = user.emails.find params[:id] not_found!('Email') unless email
email.destroy
user.update_secondary_emails! email.destroy
rescue ActiveRecord::RecordNotFound user.update_secondary_emails!
not_found!('Email')
end
end end
# Delete user. Available only for admin desc 'Delete a user. Available only for admins.' do
# success Entities::Email
# Example Request: end
# DELETE /users/:id params do
requires :id, type: Integer, desc: 'The ID of the user'
end
delete ":id" do delete ":id" do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:id]) user = User.find_by(id: params[:id])
not_found!('User') unless user
if user DeleteUserService.new(current_user).execute(user)
DeleteUserService.new(current_user).execute(user)
else
not_found!('User')
end
end end
# Block user. Available only for admin desc 'Block a user. Available only for admins.'
# params do
# Example Request: requires :id, type: Integer, desc: 'The ID of the user'
# PUT /users/:id/block end
put ':id/block' do put ':id/block' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:id]) user = User.find_by(id: params[:id])
not_found!('User') unless user
if !user if !user.ldap_blocked?
not_found!('User')
elsif !user.ldap_blocked?
user.block user.block
else else
forbidden!('LDAP blocked users cannot be modified by the API') forbidden!('LDAP blocked users cannot be modified by the API')
end end
end end
# Unblock user. Available only for admin desc 'Unblock a user. Available only for admins.'
# params do
# Example Request: requires :id, type: Integer, desc: 'The ID of the user'
# PUT /users/:id/unblock end
put ':id/unblock' do put ':id/unblock' do
authenticated_as_admin! authenticated_as_admin!
user = User.find_by(id: params[:id]) user = User.find_by(id: params[:id])
not_found!('User') unless user
if !user if user.ldap_blocked?
not_found!('User')
elsif user.ldap_blocked?
forbidden!('LDAP blocked users cannot be unblocked by the API') forbidden!('LDAP blocked users cannot be unblocked by the API')
else else
user.activate user.activate
end end
end end
desc 'Get contribution events of a specified user' do desc 'Get the contribution events of a specified user' do
detail 'This feature was introduced in GitLab 8.13.' detail 'This feature was introduced in GitLab 8.13.'
success Entities::Event success Entities::Event
end end
params do params do
requires :id, type: String, desc: 'The user ID' requires :id, type: Integer, desc: 'The ID of the user'
end end
get ':id/events' do get ':id/events' do
user = User.find_by(id: params[:id]) user = User.find_by(id: params[:id])
...@@ -349,43 +345,43 @@ module API ...@@ -349,43 +345,43 @@ module API
end end
resource :user do resource :user do
# Get currently authenticated user desc 'Get the currently authenticated user' do
# success Entities::UserFull
# Example Request: end
# GET /user
get do get do
present @current_user, with: Entities::UserFull present current_user, with: Entities::UserFull
end end
# Get currently authenticated user's keys desc "Get the currently authenticated user's SSH keys" do
# success Entities::SSHKey
# Example Request: end
# GET /user/keys
get "keys" do get "keys" do
present current_user.keys, with: Entities::SSHKey present current_user.keys, with: Entities::SSHKey
end end
# Get single key owned by currently authenticated user desc 'Get a single key owned by currently authenticated user' do
# success Entities::SSHKey
# Example Request: end
# GET /user/keys/:id params do
get "keys/:id" do requires :key_id, type: Integer, desc: 'The ID of the SSH key'
key = current_user.keys.find params[:id] end
get "keys/:key_id" do
key = current_user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
end end
# Add new ssh key to currently authenticated user desc 'Add a new SSH key to the currently authenticated user' do
# success Entities::SSHKey
# Parameters: end
# key (required) - New SSH Key params do
# title (required) - New SSH Key's title requires :key, type: String, desc: 'The new SSH key'
# Example Request: requires :title, type: String, desc: 'The title of the new SSH key'
# POST /user/keys end
post "keys" do post "keys" do
required_attributes! [:title, :key] key = current_user.keys.new(declared_params)
attrs = attributes_for_keys [:title, :key]
key = current_user.keys.new attrs
if key.save if key.save
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
else else
...@@ -393,48 +389,48 @@ module API ...@@ -393,48 +389,48 @@ module API
end end
end end
# Delete existing ssh key of currently authenticated user desc 'Delete an SSH key from the currently authenticated user' do
# success Entities::SSHKey
# Parameters: end
# id (required) - SSH Key ID params do
# Example Request: requires :key_id, type: Integer, desc: 'The ID of the SSH key'
# DELETE /user/keys/:id end
delete "keys/:id" do delete "keys/:key_id" do
begin key = current_user.keys.find_by(id: params[:key_id])
key = current_user.keys.find params[:id] not_found!('Key') unless key
key.destroy
rescue present key.destroy, with: Entities::SSHKey
end
end end
# Get currently authenticated user's emails desc "Get the currently authenticated user's email addresses" do
# success Entities::Email
# Example Request: end
# GET /user/emails
get "emails" do get "emails" do
present current_user.emails, with: Entities::Email present current_user.emails, with: Entities::Email
end end
# Get single email owned by currently authenticated user desc 'Get a single email address owned by the currently authenticated user' do
# success Entities::Email
# Example Request: end
# GET /user/emails/:id params do
get "emails/:id" do requires :email_id, type: Integer, desc: 'The ID of the email'
email = current_user.emails.find params[:id] end
get "emails/:email_id" do
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
present email, with: Entities::Email present email, with: Entities::Email
end end
# Add new email to currently authenticated user desc 'Add new email address to the currently authenticated user' do
# success Entities::Email
# Parameters: end
# email (required) - Email address params do
# Example Request: requires :email, type: String, desc: 'The new email'
# POST /user/emails end
post "emails" do post "emails" do
required_attributes! [:email] email = current_user.emails.new(declared_params)
attrs = attributes_for_keys [:email]
email = current_user.emails.new attrs
if email.save if email.save
NotificationService.new.new_email(email) NotificationService.new.new_email(email)
present email, with: Entities::Email present email, with: Entities::Email
...@@ -443,20 +439,16 @@ module API ...@@ -443,20 +439,16 @@ module API
end end
end end
# Delete existing email of currently authenticated user desc 'Delete an email address from the currently authenticated user'
# params do
# Parameters: requires :email_id, type: Integer, desc: 'The ID of the email'
# id (required) - EMail ID end
# Example Request: delete "emails/:email_id" do
# DELETE /user/emails/:id email = current_user.emails.find_by(id: params[:email_id])
delete "emails/:id" do not_found!('Email') unless email
begin
email = current_user.emails.find params[:id]
email.destroy
current_user.update_secondary_emails! email.destroy
rescue current_user.update_secondary_emails!
end
end end
end end
end end
......
...@@ -108,7 +108,7 @@ describe API::API, api: true do ...@@ -108,7 +108,7 @@ describe API::API, api: true do
it "returns a 404 error if user id not found" do it "returns a 404 error if user id not found" do
get api("/users/9999", user) get api("/users/9999", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 User Not Found')
end end
it "returns a 404 for invalid ID" do it "returns a 404 for invalid ID" do
...@@ -359,7 +359,7 @@ describe API::API, api: true do ...@@ -359,7 +359,7 @@ describe API::API, api: true do
it "returns 404 for non-existing user" do it "returns 404 for non-existing user" do
put api("/users/999999", admin), { bio: 'update should fail' } put api("/users/999999", admin), { bio: 'update should fail' }
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 User Not Found')
end end
it "returns a 404 if invalid ID" do it "returns a 404 if invalid ID" do
...@@ -387,6 +387,18 @@ describe API::API, api: true do ...@@ -387,6 +387,18 @@ describe API::API, api: true do
to eq([Gitlab::Regex.namespace_regex_message]) to eq([Gitlab::Regex.namespace_regex_message])
end end
it 'returns 400 if provider is missing for identity update' do
put api("/users/#{omniauth_user.id}", admin), extern_uid: '654321'
expect(response).to have_http_status(400)
end
it 'returns 400 if external UID is missing for identity update' do
put api("/users/#{omniauth_user.id}", admin), provider: 'ldap'
expect(response).to have_http_status(400)
end
context "with existing user" do context "with existing user" do
before do before do
post api("/users", admin), { email: 'test@example.com', password: 'password', username: 'test', name: 'test' } post api("/users", admin), { email: 'test@example.com', password: 'password', username: 'test', name: 'test' }
...@@ -414,14 +426,16 @@ describe API::API, api: true do ...@@ -414,14 +426,16 @@ describe API::API, api: true do
it "does not create invalid ssh key" do it "does not create invalid ssh key" do
post api("/users/#{user.id}/keys", admin), { title: "invalid key" } post api("/users/#{user.id}/keys", admin), { title: "invalid key" }
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "key" not given') expect(json_response['error']).to eq('key is missing')
end end
it 'does not create key without title' do it 'does not create key without title' do
post api("/users/#{user.id}/keys", admin), key: 'some key' post api("/users/#{user.id}/keys", admin), key: 'some key'
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "title" not given') expect(json_response['error']).to eq('title is missing')
end end
it "creates ssh key" do it "creates ssh key" do
...@@ -437,7 +451,7 @@ describe API::API, api: true do ...@@ -437,7 +451,7 @@ describe API::API, api: true do
end end
end end
describe 'GET /user/:uid/keys' do describe 'GET /user/:id/keys' do
before { admin } before { admin }
context 'when unauthenticated' do context 'when unauthenticated' do
...@@ -465,7 +479,7 @@ describe API::API, api: true do ...@@ -465,7 +479,7 @@ describe API::API, api: true do
end end
end end
describe 'DELETE /user/:uid/keys/:id' do describe 'DELETE /user/:id/keys/:key_id' do
before { admin } before { admin }
context 'when unauthenticated' do context 'when unauthenticated' do
...@@ -506,8 +520,9 @@ describe API::API, api: true do ...@@ -506,8 +520,9 @@ describe API::API, api: true do
it "does not create invalid email" do it "does not create invalid email" do
post api("/users/#{user.id}/emails", admin), {} post api("/users/#{user.id}/emails", admin), {}
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "email" not given') expect(json_response['error']).to eq('email is missing')
end end
it "creates email" do it "creates email" do
...@@ -524,7 +539,7 @@ describe API::API, api: true do ...@@ -524,7 +539,7 @@ describe API::API, api: true do
end end
end end
describe 'GET /user/:uid/emails' do describe 'GET /user/:id/emails' do
before { admin } before { admin }
context 'when unauthenticated' do context 'when unauthenticated' do
...@@ -558,7 +573,7 @@ describe API::API, api: true do ...@@ -558,7 +573,7 @@ describe API::API, api: true do
end end
end end
describe 'DELETE /user/:uid/emails/:id' do describe 'DELETE /user/:id/emails/:email_id' do
before { admin } before { admin }
context 'when unauthenticated' do context 'when unauthenticated' do
...@@ -673,7 +688,7 @@ describe API::API, api: true do ...@@ -673,7 +688,7 @@ describe API::API, api: true do
end end
end end
describe "GET /user/keys/:id" do describe "GET /user/keys/:key_id" do
it "returns single key" do it "returns single key" do
user.keys << key user.keys << key
user.save user.save
...@@ -686,7 +701,7 @@ describe API::API, api: true do ...@@ -686,7 +701,7 @@ describe API::API, api: true do
get api("/user/keys/42", user) get api("/user/keys/42", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 Key Not Found')
end end
it "returns 404 error if admin accesses user's ssh key" do it "returns 404 error if admin accesses user's ssh key" do
...@@ -695,7 +710,7 @@ describe API::API, api: true do ...@@ -695,7 +710,7 @@ describe API::API, api: true do
admin admin
get api("/user/keys/#{key.id}", admin) get api("/user/keys/#{key.id}", admin)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 Key Not Found')
end end
it "returns 404 for invalid ID" do it "returns 404 for invalid ID" do
...@@ -721,14 +736,16 @@ describe API::API, api: true do ...@@ -721,14 +736,16 @@ describe API::API, api: true do
it "does not create ssh key without key" do it "does not create ssh key without key" do
post api("/user/keys", user), title: 'title' post api("/user/keys", user), title: 'title'
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "key" not given') expect(json_response['error']).to eq('key is missing')
end end
it 'does not create ssh key without title' do it 'does not create ssh key without title' do
post api('/user/keys', user), key: 'some key' post api('/user/keys', user), key: 'some key'
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "title" not given') expect(json_response['error']).to eq('title is missing')
end end
it "does not create ssh key without title" do it "does not create ssh key without title" do
...@@ -737,7 +754,7 @@ describe API::API, api: true do ...@@ -737,7 +754,7 @@ describe API::API, api: true do
end end
end end
describe "DELETE /user/keys/:id" do describe "DELETE /user/keys/:key_id" do
it "deletes existed key" do it "deletes existed key" do
user.keys << key user.keys << key
user.save user.save
...@@ -747,9 +764,11 @@ describe API::API, api: true do ...@@ -747,9 +764,11 @@ describe API::API, api: true do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end end
it "returns success if key ID not found" do it "returns 404 if key ID not found" do
delete api("/user/keys/42", user) delete api("/user/keys/42", user)
expect(response).to have_http_status(200)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Key Not Found')
end end
it "returns 401 error if unauthorized" do it "returns 401 error if unauthorized" do
...@@ -786,7 +805,7 @@ describe API::API, api: true do ...@@ -786,7 +805,7 @@ describe API::API, api: true do
end end
end end
describe "GET /user/emails/:id" do describe "GET /user/emails/:email_id" do
it "returns single email" do it "returns single email" do
user.emails << email user.emails << email
user.save user.save
...@@ -798,7 +817,7 @@ describe API::API, api: true do ...@@ -798,7 +817,7 @@ describe API::API, api: true do
it "returns 404 Not Found within invalid ID" do it "returns 404 Not Found within invalid ID" do
get api("/user/emails/42", user) get api("/user/emails/42", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 Email Not Found')
end end
it "returns 404 error if admin accesses user's email" do it "returns 404 error if admin accesses user's email" do
...@@ -807,7 +826,7 @@ describe API::API, api: true do ...@@ -807,7 +826,7 @@ describe API::API, api: true do
admin admin
get api("/user/emails/#{email.id}", admin) get api("/user/emails/#{email.id}", admin)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found') expect(json_response['message']).to eq('404 Email Not Found')
end end
it "returns 404 for invalid ID" do it "returns 404 for invalid ID" do
...@@ -833,12 +852,13 @@ describe API::API, api: true do ...@@ -833,12 +852,13 @@ describe API::API, api: true do
it "does not create email with invalid email" do it "does not create email with invalid email" do
post api("/user/emails", user), {} post api("/user/emails", user), {}
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('400 (Bad request) "email" not given') expect(json_response['error']).to eq('email is missing')
end end
end end
describe "DELETE /user/emails/:id" do describe "DELETE /user/emails/:email_id" do
it "deletes existed email" do it "deletes existed email" do
user.emails << email user.emails << email
user.save user.save
...@@ -848,9 +868,11 @@ describe API::API, api: true do ...@@ -848,9 +868,11 @@ describe API::API, api: true do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end end
it "returns success if email ID not found" do it "returns 404 if email ID not found" do
delete api("/user/emails/42", user) delete api("/user/emails/42", user)
expect(response).to have_http_status(200)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Email Not Found')
end end
it "returns 401 error if unauthorized" do it "returns 401 error if unauthorized" do
...@@ -860,10 +882,10 @@ describe API::API, api: true do ...@@ -860,10 +882,10 @@ describe API::API, api: true do
expect(response).to have_http_status(401) expect(response).to have_http_status(401)
end end
it "returns a 404 for invalid ID" do it "returns 400 for invalid ID" do
delete api("/users/emails/ASDF", admin) delete api("/user/emails/ASDF", admin)
expect(response).to have_http_status(404) expect(response).to have_http_status(400)
end end
end end
......
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