Merge branch 'api-useremails' into 'master'
Add ability to manage user email addresses via the API. Addresses internal https://dev.gitlab.org/gitlab/gitlabhq/issues/2181 See merge request !1066
This commit is contained in:
commit
3f84c8a680
5 changed files with 425 additions and 6 deletions
|
@ -22,6 +22,7 @@ v 7.14.0 (unreleased)
|
|||
- Add project star and fork count, group avatar URL and user/group web URL attributes to API
|
||||
- Fix bug causing Bitbucket importer to crash when OAuth application had been removed.
|
||||
- Add fetch command to the MR page.
|
||||
- Add ability to manage user email addresses via the API.
|
||||
- Disabled autocapitalize and autocorrect on login field (Daryl Chan)
|
||||
- Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis)
|
||||
|
||||
|
|
132
doc/api/users.md
132
doc/api/users.md
|
@ -397,6 +397,138 @@ Parameters:
|
|||
|
||||
Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found.
|
||||
|
||||
## List emails
|
||||
|
||||
Get a list of currently authenticated user's emails.
|
||||
|
||||
```
|
||||
GET /user/emails
|
||||
```
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"email": "email@example.com"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"email": "email2@example.com"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- **none**
|
||||
|
||||
## List emails for user
|
||||
|
||||
Get a list of a specified user's emails. Available only for admin
|
||||
|
||||
```
|
||||
GET /users/:uid/emails
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `uid` (required) - id of specified user
|
||||
|
||||
## Single email
|
||||
|
||||
Get a single email.
|
||||
|
||||
```
|
||||
GET /user/emails/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - email ID
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"email": "email@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Add email
|
||||
|
||||
Creates a new email owned by the currently authenticated user.
|
||||
|
||||
```
|
||||
POST /user/emails
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `email` (required) - email address
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 4,
|
||||
"email": "email@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
Will return created email with status `201 Created` on success. If an
|
||||
error occurs a `400 Bad Request` is returned with a message explaining the error:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": {
|
||||
"email": [
|
||||
"has already been taken"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Add email for user
|
||||
|
||||
Create new email owned by specified user. Available only for admin
|
||||
|
||||
```
|
||||
POST /users/:id/emails
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - id of specified user
|
||||
- `email` (required) - email address
|
||||
|
||||
Will return created email with status `201 Created` on success, or `404 Not found` on fail.
|
||||
|
||||
## Delete email for current user
|
||||
|
||||
Deletes email owned by currently authenticated user.
|
||||
This is an idempotent function and calling it on a email that is already deleted
|
||||
or not available results in `200 OK`.
|
||||
|
||||
```
|
||||
DELETE /user/emails/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - email ID
|
||||
|
||||
## Delete email for given user
|
||||
|
||||
Deletes email owned by a specified user. Available only for admin.
|
||||
|
||||
```
|
||||
DELETE /users/:uid/emails/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `uid` (required) - id of specified user
|
||||
- `id` (required) - email ID
|
||||
|
||||
Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found.
|
||||
|
||||
## Block user
|
||||
|
||||
Blocks the specified user. Available only for admin.
|
||||
|
|
|
@ -35,6 +35,10 @@ module API
|
|||
expose :private_token
|
||||
end
|
||||
|
||||
class Email < Grape::Entity
|
||||
expose :id, :email
|
||||
end
|
||||
|
||||
class Hook < Grape::Entity
|
||||
expose :id, :url, :created_at
|
||||
end
|
||||
|
|
123
lib/api/users.rb
123
lib/api/users.rb
|
@ -131,11 +131,11 @@ module API
|
|||
# Add ssh key to a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a user
|
||||
# key (required) - New SSH Key
|
||||
# title (required) - New SSH Key's title
|
||||
# id (required) - The ID of a user
|
||||
# key (required) - New SSH Key
|
||||
# title (required) - New SSH Key's title
|
||||
# Example Request:
|
||||
# POST /users/:id/keys
|
||||
# POST /users/:id/keys
|
||||
post ":id/keys" do
|
||||
authenticated_as_admin!
|
||||
required_attributes! [:title, :key]
|
||||
|
@ -153,9 +153,9 @@ module API
|
|||
# Get ssh keys of a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# uid (required) - The ID of a user
|
||||
# uid (required) - The ID of a user
|
||||
# Example Request:
|
||||
# GET /users/:uid/keys
|
||||
# GET /users/:uid/keys
|
||||
get ':uid/keys' do
|
||||
authenticated_as_admin!
|
||||
user = User.find_by(id: params[:uid])
|
||||
|
@ -185,6 +185,65 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
# Add email to a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a user
|
||||
# email (required) - Email address
|
||||
# Example Request:
|
||||
# POST /users/:id/emails
|
||||
post ":id/emails" do
|
||||
authenticated_as_admin!
|
||||
required_attributes! [:email]
|
||||
|
||||
user = User.find(params[:id])
|
||||
attrs = attributes_for_keys [:email]
|
||||
email = user.emails.new attrs
|
||||
if email.save
|
||||
NotificationService.new.new_email(email)
|
||||
present email, with: Entities::Email
|
||||
else
|
||||
render_validation_error!(email)
|
||||
end
|
||||
end
|
||||
|
||||
# Get emails of a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# uid (required) - The ID of a user
|
||||
# Example Request:
|
||||
# GET /users/:uid/emails
|
||||
get ':uid/emails' do
|
||||
authenticated_as_admin!
|
||||
user = User.find_by(id: params[:uid])
|
||||
not_found!('User') unless user
|
||||
|
||||
present user.emails, with: Entities::Email
|
||||
end
|
||||
|
||||
# Delete existing email of a specified user. Only available to admin
|
||||
# users.
|
||||
#
|
||||
# Parameters:
|
||||
# uid (required) - The ID of a user
|
||||
# id (required) - Email ID
|
||||
# Example Request:
|
||||
# DELETE /users/:uid/emails/:id
|
||||
delete ':uid/emails/:id' do
|
||||
authenticated_as_admin!
|
||||
user = User.find_by(id: params[:uid])
|
||||
not_found!('User') unless user
|
||||
|
||||
begin
|
||||
email = user.emails.find params[:id]
|
||||
email.destroy
|
||||
|
||||
user.update_secondary_emails!
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
not_found!('Email')
|
||||
end
|
||||
end
|
||||
|
||||
# Delete user. Available only for admin
|
||||
#
|
||||
# Example Request:
|
||||
|
@ -289,6 +348,58 @@ module API
|
|||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
# Get currently authenticated user's emails
|
||||
#
|
||||
# Example Request:
|
||||
# GET /user/emails
|
||||
get "emails" do
|
||||
present current_user.emails, with: Entities::Email
|
||||
end
|
||||
|
||||
# Get single email owned by currently authenticated user
|
||||
#
|
||||
# Example Request:
|
||||
# GET /user/emails/:id
|
||||
get "emails/:id" do
|
||||
email = current_user.emails.find params[:id]
|
||||
present email, with: Entities::Email
|
||||
end
|
||||
|
||||
# Add new email to currently authenticated user
|
||||
#
|
||||
# Parameters:
|
||||
# email (required) - Email address
|
||||
# Example Request:
|
||||
# POST /user/emails
|
||||
post "emails" do
|
||||
required_attributes! [:email]
|
||||
|
||||
attrs = attributes_for_keys [:email]
|
||||
email = current_user.emails.new attrs
|
||||
if email.save
|
||||
NotificationService.new.new_email(email)
|
||||
present email, with: Entities::Email
|
||||
else
|
||||
render_validation_error!(email)
|
||||
end
|
||||
end
|
||||
|
||||
# Delete existing email of currently authenticated user
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - EMail ID
|
||||
# Example Request:
|
||||
# DELETE /user/emails/:id
|
||||
delete "emails/:id" do
|
||||
begin
|
||||
email = current_user.emails.find params[:id]
|
||||
email.destroy
|
||||
|
||||
current_user.update_secondary_emails!
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ describe API::API, api: true do
|
|||
let(:user) { create(:user) }
|
||||
let(:admin) { create(:admin) }
|
||||
let(:key) { create(:key, user: user) }
|
||||
let(:email) { create(:email, user: user) }
|
||||
|
||||
describe "GET /users" do
|
||||
context "when unauthenticated" do
|
||||
|
@ -384,6 +385,87 @@ describe API::API, api: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe "POST /users/:id/emails" do
|
||||
before { admin }
|
||||
|
||||
it "should not create invalid email" do
|
||||
post api("/users/#{user.id}/emails", admin), {}
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('400 (Bad request) "email" not given')
|
||||
end
|
||||
|
||||
it "should create email" do
|
||||
email_attrs = attributes_for :email
|
||||
expect do
|
||||
post api("/users/#{user.id}/emails", admin), email_attrs
|
||||
end.to change{ user.emails.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /user/:uid/emails' do
|
||||
before { admin }
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'should return authentication error' do
|
||||
get api("/users/#{user.id}/emails")
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
it 'should return 404 for non-existing user' do
|
||||
get api('/users/999999/emails', admin)
|
||||
expect(response.status).to eq(404)
|
||||
expect(json_response['message']).to eq('404 User Not Found')
|
||||
end
|
||||
|
||||
it 'should return array of emails' do
|
||||
user.emails << email
|
||||
user.save
|
||||
get api("/users/#{user.id}/emails", admin)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.first['email']).to eq(email.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /user/:uid/emails/:id' do
|
||||
before { admin }
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'should return authentication error' do
|
||||
delete api("/users/#{user.id}/emails/42")
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
it 'should delete existing email' do
|
||||
user.emails << email
|
||||
user.save
|
||||
expect do
|
||||
delete api("/users/#{user.id}/emails/#{email.id}", admin)
|
||||
end.to change { user.emails.count }.by(-1)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it 'should return 404 error if user not found' do
|
||||
user.emails << email
|
||||
user.save
|
||||
delete api("/users/999999/emails/#{email.id}", admin)
|
||||
expect(response.status).to eq(404)
|
||||
expect(json_response['message']).to eq('404 User Not Found')
|
||||
end
|
||||
|
||||
it 'should return 404 error if email not foud' do
|
||||
delete api("/users/#{user.id}/emails/42", admin)
|
||||
expect(response.status).to eq(404)
|
||||
expect(json_response['message']).to eq('404 Email Not Found')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /users/:id" do
|
||||
before { admin }
|
||||
|
||||
|
@ -528,6 +610,95 @@ describe API::API, api: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe "GET /user/emails" do
|
||||
context "when unauthenticated" do
|
||||
it "should return authentication error" do
|
||||
get api("/user/emails")
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context "when authenticated" do
|
||||
it "should return array of emails" do
|
||||
user.emails << email
|
||||
user.save
|
||||
get api("/user/emails", user)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.first["email"]).to eq(email.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /user/emails/:id" do
|
||||
it "should return single email" do
|
||||
user.emails << email
|
||||
user.save
|
||||
get api("/user/emails/#{email.id}", user)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response["email"]).to eq(email.email)
|
||||
end
|
||||
|
||||
it "should return 404 Not Found within invalid ID" do
|
||||
get api("/user/emails/42", user)
|
||||
expect(response.status).to eq(404)
|
||||
expect(json_response['message']).to eq('404 Not found')
|
||||
end
|
||||
|
||||
it "should return 404 error if admin accesses user's email" do
|
||||
user.emails << email
|
||||
user.save
|
||||
admin
|
||||
get api("/user/emails/#{email.id}", admin)
|
||||
expect(response.status).to eq(404)
|
||||
expect(json_response['message']).to eq('404 Not found')
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /user/emails" do
|
||||
it "should create email" do
|
||||
email_attrs = attributes_for :email
|
||||
expect do
|
||||
post api("/user/emails", user), email_attrs
|
||||
end.to change{ user.emails.count }.by(1)
|
||||
expect(response.status).to eq(201)
|
||||
end
|
||||
|
||||
it "should return a 401 error if unauthorized" do
|
||||
post api("/user/emails"), email: 'some email'
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
|
||||
it "should not create email with invalid email" do
|
||||
post api("/user/emails", user), {}
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('400 (Bad request) "email" not given')
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /user/emails/:id" do
|
||||
it "should delete existed email" do
|
||||
user.emails << email
|
||||
user.save
|
||||
expect do
|
||||
delete api("/user/emails/#{email.id}", user)
|
||||
end.to change{user.emails.count}.by(-1)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it "should return success if email ID not found" do
|
||||
delete api("/user/emails/42", user)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it "should return 401 error if unauthorized" do
|
||||
user.emails << email
|
||||
user.save
|
||||
delete api("/user/emails/#{email.id}")
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /user/:id/block' do
|
||||
before { admin }
|
||||
it 'should block existing user' do
|
||||
|
|
Loading…
Reference in a new issue