Commit d6f20b55 authored by Stan Hu's avatar Stan Hu

Add support for creating random passwords in user creation API

To avoid having to specify an actual password to create users, admins
can now use the `force_random_password` parameter to let Devise generate
a password.

Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/63826
parent e29a5136
---
title: Add support for creating random passwords in user creation API
merge_request: 30138
author:
type: changed
...@@ -272,7 +272,14 @@ GET /users/:id?with_custom_attributes=true ...@@ -272,7 +272,14 @@ GET /users/:id?with_custom_attributes=true
## User creation ## User creation
Creates a new user. Note only administrators can create new users. Either `password` or `reset_password` should be specified (`reset_password` takes priority). If `reset_password` is `false`, then `password` is required. Creates a new user. Note only administrators can create new
users. Either `password`, `reset_password`, or `force_random_password`
must be specified. If `reset_password` and `force_random_password` are
both `false`, then `password` is required.
Note that `force_random_password` and `reset_password` take priority
over `password`. In addition, `reset_password` and
`force_random_password` can be used together.
``` ```
POST /users POST /users
...@@ -280,29 +287,30 @@ POST /users ...@@ -280,29 +287,30 @@ POST /users
Parameters: Parameters:
- `email` (required) - Email - `email` (required) - Email
- `password` (optional) - Password - `password` (optional) - Password
- `reset_password` (optional) - Send user password reset link - true or false(default) - `reset_password` (optional) - Send user password reset link - true or false (default)
- `username` (required) - Username - `force_random_password` (optional) - Set user password to a random value - true or false (default)
- `name` (required) - Name - `username` (required) - Username
- `skype` (optional) - Skype ID - `name` (required) - Name
- `linkedin` (optional) - LinkedIn - `skype` (optional) - Skype ID
- `twitter` (optional) - Twitter account - `linkedin` (optional) - LinkedIn
- `website_url` (optional) - Website URL - `twitter` (optional) - Twitter account
- `organization` (optional) - Organization name - `website_url` (optional) - Website URL
- `projects_limit` (optional) - Number of projects user can create - `organization` (optional) - Organization name
- `extern_uid` (optional) - External UID - `projects_limit` (optional) - Number of projects user can create
- `provider` (optional) - External provider name - `extern_uid` (optional) - External UID
- `group_id_for_saml` (optional) - ID of group where SAML has been configured - `provider` (optional) - External provider name
- `bio` (optional) - User's biography - `group_id_for_saml` (optional) - ID of group where SAML has been configured
- `location` (optional) - User's location - `bio` (optional) - User's biography
- `public_email` (optional) - The public email of the user - `location` (optional) - User's location
- `admin` (optional) - User is admin - true or false (default) - `public_email` (optional) - The public email of the user
- `can_create_group` (optional) - User can create groups - true or false - `admin` (optional) - User is admin - true or false (default)
- `skip_confirmation` (optional) - Skip confirmation - true or false (default) - `can_create_group` (optional) - User can create groups - true or false
- `external` (optional) - Flags the user as external - true or false(default) - `skip_confirmation` (optional) - Skip confirmation - true or false (default)
- `avatar` (optional) - Image file for user's avatar - `external` (optional) - Flags the user as external - true or false(default)
- `private_profile` (optional) - User's profile is private - true or false - `avatar` (optional) - Image file for user's avatar
- `private_profile` (optional) - User's profile is private - true or false
- `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user - `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user
- `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user - `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user
......
...@@ -158,6 +158,7 @@ module API ...@@ -158,6 +158,7 @@ module API
at_least_one_of :password, :reset_password at_least_one_of :password, :reset_password
requires :name, type: String, desc: 'The name of the user' requires :name, type: String, desc: 'The name of the user'
requires :username, type: String, desc: 'The username of the user' requires :username, type: String, desc: 'The username of the user'
optional :force_random_password, type: Boolean, desc: 'Flag indicating a random password will be set'
use :optional_attributes use :optional_attributes
end end
post do post do
......
...@@ -416,7 +416,6 @@ describe API::Users do ...@@ -416,7 +416,6 @@ describe API::Users do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq(nil)
expect(new_user.admin).to eq(true) expect(new_user.admin).to eq(true)
expect(new_user.can_create_group).to eq(true) expect(new_user.can_create_group).to eq(true)
end end
...@@ -435,7 +434,6 @@ describe API::Users do ...@@ -435,7 +434,6 @@ describe API::Users do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq(nil)
expect(new_user.admin).to eq(false) expect(new_user.admin).to eq(false)
expect(new_user.can_create_group).to eq(false) expect(new_user.can_create_group).to eq(false)
end end
...@@ -445,7 +443,6 @@ describe API::Users do ...@@ -445,7 +443,6 @@ describe API::Users do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq(nil)
expect(new_user.admin).to eq(false) expect(new_user.admin).to eq(false)
end end
...@@ -460,7 +457,6 @@ describe API::Users do ...@@ -460,7 +457,6 @@ describe API::Users do
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq nil
expect(new_user.external).to be_falsy expect(new_user.external).to be_falsy
end end
...@@ -470,7 +466,6 @@ describe API::Users do ...@@ -470,7 +466,6 @@ describe API::Users do
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq nil
expect(new_user.external).to be_truthy expect(new_user.external).to be_truthy
end end
...@@ -482,7 +477,19 @@ describe API::Users do ...@@ -482,7 +477,19 @@ describe API::Users do
user_id = json_response['id'] user_id = json_response['id']
new_user = User.find(user_id) new_user = User.find(user_id)
expect(new_user).not_to eq(nil) expect(new_user.recently_sent_password_reset?).to eq(true)
end
it "creates user with random password" do
params = attributes_for(:user, force_random_password: true, reset_password: true)
post api('/users', admin), params: params
expect(response).to have_gitlab_http_status(201)
user_id = json_response['id']
new_user = User.find(user_id)
expect(new_user.valid_password?(params[:password])).to eq(false)
expect(new_user.recently_sent_password_reset?).to eq(true) expect(new_user.recently_sent_password_reset?).to eq(true)
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