Commit 836104b41a557e8411d422c0dca7930e85b0de95
Exists in
master
and in
4 other branches
Merge pull request #5213 from bladealslayer/feature/user_api_extended
Extended User API to expose admin and can_create_group for user creation...
Showing
5 changed files
with
85 additions
and
24 deletions
Show diff stats
doc/api/users.md
| @@ -23,7 +23,9 @@ GET /users | @@ -23,7 +23,9 @@ GET /users | ||
| 23 | "extern_uid": "john.smith", | 23 | "extern_uid": "john.smith", |
| 24 | "provider": "provider_name", | 24 | "provider": "provider_name", |
| 25 | "theme_id": 1, | 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 | "id": 2, | 31 | "id": 2, |
| @@ -39,7 +41,9 @@ GET /users | @@ -39,7 +41,9 @@ GET /users | ||
| 39 | "extern_uid": "jack.smith", | 41 | "extern_uid": "jack.smith", |
| 40 | "provider": "provider_name", | 42 | "provider": "provider_name", |
| 41 | "theme_id": 1, | 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,7 +76,9 @@ Parameters: | ||
| 72 | "extern_uid": "john.smith", | 76 | "extern_uid": "john.smith", |
| 73 | "provider": "provider_name", | 77 | "provider": "provider_name", |
| 74 | "theme_id": 1, | 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,17 +93,19 @@ POST /users | ||
| 87 | 93 | ||
| 88 | Parameters: | 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 | ## User modification | 111 | ## User modification |
| @@ -121,6 +129,8 @@ Parameters: | @@ -121,6 +129,8 @@ Parameters: | ||
| 121 | + `extern_uid` - External UID | 129 | + `extern_uid` - External UID |
| 122 | + `provider` - External provider name | 130 | + `provider` - External provider name |
| 123 | + `bio` - User's bio | 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 | Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would | 135 | Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would |
| 126 | be more appropriate, e.g. when renaming the email address to some existing one. | 136 | be more appropriate, e.g. when renaming the email address to some existing one. |
| @@ -166,7 +176,6 @@ GET /user | @@ -166,7 +176,6 @@ GET /user | ||
| 166 | "color_scheme_id": 2, | 176 | "color_scheme_id": 2, |
| 167 | "is_admin": false, | 177 | "is_admin": false, |
| 168 | "can_create_group" : true, | 178 | "can_create_group" : true, |
| 169 | - "can_create_team" : true, | ||
| 170 | "can_create_project" : true | 179 | "can_create_project" : true |
| 171 | } | 180 | } |
| 172 | ``` | 181 | ``` |
lib/api/entities.rb
| @@ -3,6 +3,9 @@ module API | @@ -3,6 +3,9 @@ module API | ||
| 3 | class User < Grape::Entity | 3 | class User < Grape::Entity |
| 4 | expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, | 4 | expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, |
| 5 | :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider | 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 | end | 9 | end |
| 7 | 10 | ||
| 8 | class UserSafe < Grape::Entity | 11 | class UserSafe < Grape::Entity |
| @@ -15,10 +18,6 @@ module API | @@ -15,10 +18,6 @@ module API | ||
| 15 | 18 | ||
| 16 | class UserLogin < User | 19 | class UserLogin < User |
| 17 | expose :private_token | 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 | end | 21 | end |
| 23 | 22 | ||
| 24 | class Hook < Grape::Entity | 23 | class Hook < Grape::Entity |
lib/api/helpers.rb
| @@ -86,7 +86,7 @@ module API | @@ -86,7 +86,7 @@ module API | ||
| 86 | def attributes_for_keys(keys) | 86 | def attributes_for_keys(keys) |
| 87 | attrs = {} | 87 | attrs = {} |
| 88 | keys.each do |key| | 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 | end | 90 | end |
| 91 | attrs | 91 | attrs |
| 92 | end | 92 | end |
lib/api/users.rb
| @@ -40,13 +40,17 @@ module API | @@ -40,13 +40,17 @@ module API | ||
| 40 | # extern_uid - External authentication provider UID | 40 | # extern_uid - External authentication provider UID |
| 41 | # provider - External provider | 41 | # provider - External provider |
| 42 | # bio - Bio | 42 | # bio - Bio |
| 43 | + # admin - User is admin - true or false (default) | ||
| 44 | + # can_create_group - User can create groups - true or false | ||
| 43 | # Example Request: | 45 | # Example Request: |
| 44 | # POST /users | 46 | # POST /users |
| 45 | post do | 47 | post do |
| 46 | authenticated_as_admin! | 48 | authenticated_as_admin! |
| 47 | required_attributes! [:email, :password, :name, :username] | 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 | user = User.build_user(attrs, as: :admin) | 51 | user = User.build_user(attrs, as: :admin) |
| 52 | + admin = attrs.delete(:admin) | ||
| 53 | + user.admin = admin unless admin.nil? | ||
| 50 | if user.save | 54 | if user.save |
| 51 | present user, with: Entities::User | 55 | present user, with: Entities::User |
| 52 | else | 56 | else |
| @@ -67,16 +71,20 @@ module API | @@ -67,16 +71,20 @@ module API | ||
| 67 | # extern_uid - External authentication provider UID | 71 | # extern_uid - External authentication provider UID |
| 68 | # provider - External provider | 72 | # provider - External provider |
| 69 | # bio - Bio | 73 | # bio - Bio |
| 74 | + # admin - User is admin - true or false (default) | ||
| 75 | + # can_create_group - User can create groups - true or false | ||
| 70 | # Example Request: | 76 | # Example Request: |
| 71 | # PUT /users/:id | 77 | # PUT /users/:id |
| 72 | put ":id" do | 78 | put ":id" do |
| 73 | authenticated_as_admin! | 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 | user = User.find(params[:id]) | 82 | user = User.find(params[:id]) |
| 77 | not_found!("User not found") unless user | 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 | present user, with: Entities::User | 88 | present user, with: Entities::User |
| 81 | else | 89 | else |
| 82 | not_found! | 90 | not_found! |
spec/requests/api/users_spec.rb
| @@ -52,6 +52,35 @@ describe API::API do | @@ -52,6 +52,35 @@ describe API::API do | ||
| 52 | }.to change { User.count }.by(1) | 52 | }.to change { User.count }.by(1) |
| 53 | end | 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 | it "should return 201 Created on success" do | 84 | it "should return 201 Created on success" do |
| 56 | post api("/users", admin), attributes_for(:user, projects_limit: 3) | 85 | post api("/users", admin), attributes_for(:user, projects_limit: 3) |
| 57 | response.status.should == 201 | 86 | response.status.should == 201 |
| @@ -135,6 +164,8 @@ describe API::API do | @@ -135,6 +164,8 @@ describe API::API do | ||
| 135 | end | 164 | end |
| 136 | 165 | ||
| 137 | describe "PUT /users/:id" do | 166 | describe "PUT /users/:id" do |
| 167 | + let!(:admin_user) { create(:admin) } | ||
| 168 | + | ||
| 138 | before { admin } | 169 | before { admin } |
| 139 | 170 | ||
| 140 | it "should update user with new bio" do | 171 | it "should update user with new bio" do |
| @@ -144,6 +175,21 @@ describe API::API do | @@ -144,6 +175,21 @@ describe API::API do | ||
| 144 | user.reload.bio.should == 'new test bio' | 175 | user.reload.bio.should == 'new test bio' |
| 145 | end | 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 | it "should not allow invalid update" do | 193 | it "should not allow invalid update" do |
| 148 | put api("/users/#{user.id}", admin), {email: 'invalid email'} | 194 | put api("/users/#{user.id}", admin), {email: 'invalid email'} |
| 149 | response.status.should == 404 | 195 | response.status.should == 404 |
| @@ -228,7 +274,6 @@ describe API::API do | @@ -228,7 +274,6 @@ describe API::API do | ||
| 228 | response.status.should == 200 | 274 | response.status.should == 200 |
| 229 | json_response['email'].should == user.email | 275 | json_response['email'].should == user.email |
| 230 | json_response['is_admin'].should == user.is_admin? | 276 | json_response['is_admin'].should == user.is_admin? |
| 231 | - json_response['can_create_team'].should == user.can_create_team? | ||
| 232 | json_response['can_create_project'].should == user.can_create_project? | 277 | json_response['can_create_project'].should == user.can_create_project? |
| 233 | json_response['can_create_group'].should == user.can_create_group? | 278 | json_response['can_create_group'].should == user.can_create_group? |
| 234 | end | 279 | end |