From e954438a1d3a45addebf52ab04155459d7d84db0 Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Tue, 18 Dec 2012 21:24:31 +0200
Subject: [PATCH] Extended users API to support updating and deleting users.

Also added tests.
---
 doc/api/users.md                | 43 +++++++++++++++++++++++++++++
 lib/api/entities.rb             |  2 +-
 lib/api/users.rb                | 47 +++++++++++++++++++++++++++++++-
 spec/requests/api/users_spec.rb | 48 +++++++++++++++++++++++++++++++++
 4 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/doc/api/users.md b/doc/api/users.md
index 200c0e06e04..b94d7c0f789 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -20,6 +20,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": false,
+    "extern_uid": "john.smith",
+    "provider": "provider_name",
     "theme_id": 1
   },
   {
@@ -34,6 +36,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": true,
+    "extern_uid": "jack.smith",
+    "provider": "provider_name",
     "theme_id": 1
   }
 ]
@@ -64,6 +68,8 @@ Parameters:
   "linkedin": "",
   "twitter": "",
   "dark_scheme": false,
+  "extern_uid": "john.smith",
+  "provider": "provider_name",
   "theme_id": 1
 }
 ```
@@ -84,10 +90,47 @@ Parameters:
 + `linkedin`                          - Linkedin
 + `twitter`                           - Twitter account
 + `projects_limit`                    - Number of projects user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
 
 Will return created user with status `201 Created` on success, or `404 Not
 found` on fail.
 
+## User modification
+Modify user. Available only for admin
+
+```
+PUT /users/:id
+```
+
+Parameters:
++ `email`                             - Email
++ `username`                          - Username
++ `name`                              - Name
++ `password`                          - Password
++ `skype`                             - Skype ID
++ `linkedin`                          - Linkedin
++ `twitter`                           - Twitter account
++ `projects_limit`                    - Limit projects wich user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
+
+
+Will return created user with status `200 OK` on success, or `404 Not
+found` on fail.
+
+## User deletion
+Delete user. Available only for admin
+
+```
+DELETE /users/:id
+```
+
+Will return deleted user with status `200 OK` on success, or `404 Not
+found` on fail.
+
 ## Current user
 
 Get currently authenticated user.
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 070fbad27ed..bfb9093d61e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -2,7 +2,7 @@ module Gitlab
   module Entities
     class User < Grape::Entity
       expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
-             :dark_scheme, :theme_id, :blocked, :created_at
+             :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider
     end
 
     class UserBasic < Grape::Entity
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 140c20f6bd2..7ea90c75e9e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -34,11 +34,14 @@ module Gitlab
       #   linkedin                          - Linkedin
       #   twitter                           - Twitter account
       #   projects_limit                    - Number of projects user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
         user = User.new attrs, as: :admin
         if user.save
           present user, with: Entities::User
@@ -46,6 +49,48 @@ module Gitlab
           not_found!
         end
       end
+
+      # Update user. Available only for admin
+      #
+      # Parameters:
+      #   email                             - Email
+      #   name                              - Name
+      #   password                          - Password
+      #   skype                             - Skype ID
+      #   linkedin                          - Linkedin
+      #   twitter                           - Twitter account
+      #   projects_limit                    - Limit projects wich user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
+      # Example Request:
+      #   PUT /users/:id
+      put ":id" do
+        authenticated_as_admin!
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        user = User.find_by_id(params[:id])
+
+        if user && user.update_attributes(attrs)
+          present user, with: Entities::User
+        else
+          not_found!
+        end
+      end
+
+      # Delete user. Available only for admin
+      #
+      # Example Request:
+      #   DELETE /users/:id
+      delete ":id" do
+        authenticated_as_admin!
+        user = User.find_by_id(params[:id])
+
+        if user
+          user.destroy
+        else
+          not_found!
+        end
+      end
     end
 
     resource :user do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 4cfb4884e7c..108d1bf9458 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -53,6 +53,54 @@ describe Gitlab::API do
     end
   end
 
+  describe "PUT /users/:id" do
+    before { admin }
+
+    it "should update user" do
+      put api("/users/#{user.id}", admin), {bio: 'new test bio'}
+      response.status.should == 200
+      json_response['bio'].should == 'new test bio'
+      user.reload.bio.should == 'new test bio'
+    end
+
+    it "should not allow invalid update" do
+      put api("/users/#{user.id}", admin), {email: 'invalid email'}
+      response.status.should == 404
+      user.reload.email.should_not == 'invalid email'
+    end
+
+    it "shouldn't available for non admin users" do
+      put api("/users/#{user.id}", user), attributes_for(:user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      put api("/users/999999", admin), {bio: 'update should fail'}
+      response.status.should == 404
+    end
+  end
+
+  describe "DELETE /users/:id" do
+    before { admin }
+
+    it "should delete user" do
+      delete api("/users/#{user.id}", admin)
+      response.status.should == 200
+      expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
+      json_response['email'].should == user.email
+    end
+
+    it "shouldn't available for non admin users" do
+      delete api("/users/#{user.id}", user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      delete api("/users/999999", admin)
+      response.status.should == 404
+    end
+  end
+
   describe "GET /user" do
     it "should return current user" do
       get api("/user", user)
-- 
GitLab