Commit 836104b41a557e8411d422c0dca7930e85b0de95

Authored by Dmitriy Zaporozhets
2 parents e48c6fab 5b657a65

Merge pull request #5213 from bladealslayer/feature/user_api_extended

Extended User API to expose admin and can_create_group for user creation...
doc/api/users.md
... ... @@ -23,7 +23,9 @@ GET /users
23 23 "extern_uid": "john.smith",
24 24 "provider": "provider_name",
25 25 "theme_id": 1,
26   - "color_scheme_id": 2
  26 + "color_scheme_id": 2,
  27 + "is_admin": false,
  28 + "can_create_group": true
27 29 },
28 30 {
29 31 "id": 2,
... ... @@ -39,7 +41,9 @@ GET /users
39 41 "extern_uid": "jack.smith",
40 42 "provider": "provider_name",
41 43 "theme_id": 1,
42   - "color_scheme_id": 3
  44 + "color_scheme_id": 3,
  45 + "is_admin": false,
  46 + "can_create_group": true
43 47 }
44 48 ]
45 49 ```
... ... @@ -72,7 +76,9 @@ Parameters:
72 76 "extern_uid": "john.smith",
73 77 "provider": "provider_name",
74 78 "theme_id": 1,
75   - "color_scheme_id": 2
  79 + "color_scheme_id": 2,
  80 + "is_admin": false,
  81 + "can_create_group": true
76 82 }
77 83 ```
78 84  
... ... @@ -87,17 +93,19 @@ POST /users
87 93  
88 94 Parameters:
89 95  
90   -+ `email` (required) - Email
91   -+ `password` (required) - Password
92   -+ `username` (required) - Username
93   -+ `name` (required) - Name
94   -+ `skype` (optional) - Skype ID
95   -+ `linkedin` (optional) - Linkedin
96   -+ `twitter` (optional) - Twitter account
97   -+ `projects_limit` (optional) - Number of projects user can create
98   -+ `extern_uid` (optional) - External UID
99   -+ `provider` (optional) - External provider name
100   -+ `bio` (optional) - User's bio
  96 ++ `email` (required) - Email
  97 ++ `password` (required) - Password
  98 ++ `username` (required) - Username
  99 ++ `name` (required) - Name
  100 ++ `skype` (optional) - Skype ID
  101 ++ `linkedin` (optional) - Linkedin
  102 ++ `twitter` (optional) - Twitter account
  103 ++ `projects_limit` (optional) - Number of projects user can create
  104 ++ `extern_uid` (optional) - External UID
  105 ++ `provider` (optional) - External provider name
  106 ++ `bio` (optional) - User's bio
  107 ++ `admin` (optional) - User is admin - true or false (default)
  108 ++ `can_create_group` (optional) - User can create groups - true or false
101 109  
102 110  
103 111 ## User modification
... ... @@ -121,6 +129,8 @@ Parameters:
121 129 + `extern_uid` - External UID
122 130 + `provider` - External provider name
123 131 + `bio` - User's bio
  132 ++ `admin` (optional) - User is admin - true or false (default)
  133 ++ `can_create_group` (optional) - User can create groups - true or false
124 134  
125 135 Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would
126 136 be more appropriate, e.g. when renaming the email address to some existing one.
... ... @@ -166,7 +176,6 @@ GET /user
166 176 "color_scheme_id": 2,
167 177 "is_admin": false,
168 178 "can_create_group" : true,
169   - "can_create_team" : true,
170 179 "can_create_project" : true
171 180 }
172 181 ```
... ...
lib/api/entities.rb
... ... @@ -3,6 +3,9 @@ module API
3 3 class User < Grape::Entity
4 4 expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
5 5 :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider
  6 + expose :is_admin?, as: :is_admin
  7 + expose :can_create_group?, as: :can_create_group
  8 + expose :can_create_project?, as: :can_create_project
6 9 end
7 10  
8 11 class UserSafe < Grape::Entity
... ... @@ -15,10 +18,6 @@ module API
15 18  
16 19 class UserLogin < User
17 20 expose :private_token
18   - expose :is_admin?, as: :is_admin
19   - expose :can_create_group?, as: :can_create_group
20   - expose :can_create_project?, as: :can_create_project
21   - expose :can_create_team?, as: :can_create_team
22 21 end
23 22  
24 23 class Hook < Grape::Entity
... ...
lib/api/helpers.rb
... ... @@ -86,7 +86,7 @@ module API
86 86 def attributes_for_keys(keys)
87 87 attrs = {}
88 88 keys.each do |key|
89   - attrs[key] = params[key] if params[key].present?
  89 + attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)
90 90 end
91 91 attrs
92 92 end
... ...
lib/api/users.rb
... ... @@ -40,13 +40,17 @@ module API
40 40 # extern_uid - External authentication provider UID
41 41 # provider - External provider
42 42 # bio - Bio
  43 + # admin - User is admin - true or false (default)
  44 + # can_create_group - User can create groups - true or false
43 45 # Example Request:
44 46 # POST /users
45 47 post do
46 48 authenticated_as_admin!
47 49 required_attributes! [:email, :password, :name, :username]
48   - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
  50 + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
49 51 user = User.build_user(attrs, as: :admin)
  52 + admin = attrs.delete(:admin)
  53 + user.admin = admin unless admin.nil?
50 54 if user.save
51 55 present user, with: Entities::User
52 56 else
... ... @@ -67,16 +71,20 @@ module API
67 71 # extern_uid - External authentication provider UID
68 72 # provider - External provider
69 73 # bio - Bio
  74 + # admin - User is admin - true or false (default)
  75 + # can_create_group - User can create groups - true or false
70 76 # Example Request:
71 77 # PUT /users/:id
72 78 put ":id" do
73 79 authenticated_as_admin!
74 80  
75   - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
  81 + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
76 82 user = User.find(params[:id])
77 83 not_found!("User not found") unless user
78 84  
79   - if user.update_attributes(attrs)
  85 + admin = attrs.delete(:admin)
  86 + user.admin = admin unless admin.nil?
  87 + if user.update_attributes(attrs, as: :admin)
80 88 present user, with: Entities::User
81 89 else
82 90 not_found!
... ...
spec/requests/api/users_spec.rb
... ... @@ -52,6 +52,35 @@ describe API::API do
52 52 }.to change { User.count }.by(1)
53 53 end
54 54  
  55 + it "should create user with correct attributes" do
  56 + post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true)
  57 + response.status.should == 201
  58 + user_id = json_response['id']
  59 + new_user = User.find(user_id)
  60 + new_user.should_not == nil
  61 + new_user.admin.should == true
  62 + new_user.can_create_group.should == true
  63 + end
  64 +
  65 + it "should create non-admin user" do
  66 + post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false)
  67 + response.status.should == 201
  68 + user_id = json_response['id']
  69 + new_user = User.find(user_id)
  70 + new_user.should_not == nil
  71 + new_user.admin.should == false
  72 + new_user.can_create_group.should == false
  73 + end
  74 +
  75 + it "should create non-admin users by default" do
  76 + post api('/users', admin), attributes_for(:user)
  77 + response.status.should == 201
  78 + user_id = json_response['id']
  79 + new_user = User.find(user_id)
  80 + new_user.should_not == nil
  81 + new_user.admin.should == false
  82 + end
  83 +
55 84 it "should return 201 Created on success" do
56 85 post api("/users", admin), attributes_for(:user, projects_limit: 3)
57 86 response.status.should == 201
... ... @@ -135,6 +164,8 @@ describe API::API do
135 164 end
136 165  
137 166 describe "PUT /users/:id" do
  167 + let!(:admin_user) { create(:admin) }
  168 +
138 169 before { admin }
139 170  
140 171 it "should update user with new bio" do
... ... @@ -144,6 +175,21 @@ describe API::API do
144 175 user.reload.bio.should == 'new test bio'
145 176 end
146 177  
  178 + it "should update admin status" do
  179 + put api("/users/#{user.id}", admin), {admin: true}
  180 + response.status.should == 200
  181 + json_response['is_admin'].should == true
  182 + user.reload.admin.should == true
  183 + end
  184 +
  185 + it "should not update admin status" do
  186 + put api("/users/#{admin_user.id}", admin), {can_create_group: false}
  187 + response.status.should == 200
  188 + json_response['is_admin'].should == true
  189 + admin_user.reload.admin.should == true
  190 + admin_user.can_create_group.should == false
  191 + end
  192 +
147 193 it "should not allow invalid update" do
148 194 put api("/users/#{user.id}", admin), {email: 'invalid email'}
149 195 response.status.should == 404
... ... @@ -228,7 +274,6 @@ describe API::API do
228 274 response.status.should == 200
229 275 json_response['email'].should == user.email
230 276 json_response['is_admin'].should == user.is_admin?
231   - json_response['can_create_team'].should == user.can_create_team?
232 277 json_response['can_create_project'].should == user.can_create_project?
233 278 json_response['can_create_group'].should == user.can_create_group?
234 279 end
... ...