Commit 6838304a85cd3b5dfdac076c600cb15f5643c674
1 parent
00882b3c
Exists in
master
and in
4 other branches
Force user password change for users created by admin
Showing
9 changed files
with
118 additions
and
76 deletions
Show diff stats
app/controllers/admin/users_controller.rb
| ... | ... | @@ -55,8 +55,14 @@ class Admin::UsersController < Admin::ApplicationController |
| 55 | 55 | def create |
| 56 | 56 | admin = params[:user].delete("admin") |
| 57 | 57 | |
| 58 | - @admin_user = User.new(params[:user], as: :admin) | |
| 58 | + opts = { | |
| 59 | + force_random_password: true, | |
| 60 | + password_expires_at: Time.now | |
| 61 | + } | |
| 62 | + | |
| 63 | + @admin_user = User.new(params[:user].merge(opts), as: :admin) | |
| 59 | 64 | @admin_user.admin = (admin && admin.to_i > 0) |
| 65 | + @admin_user.created_by_id = current_user.id | |
| 60 | 66 | |
| 61 | 67 | respond_to do |format| |
| 62 | 68 | if @admin_user.save | ... | ... |
app/models/user.rb
app/views/admin/users/_form.html.haml
| ... | ... | @@ -24,19 +24,25 @@ |
| 24 | 24 | = f.text_field :email, required: true, autocomplete: "off" |
| 25 | 25 | %span.help-inline * required |
| 26 | 26 | |
| 27 | - %fieldset | |
| 28 | - %legend Password | |
| 29 | - .clearfix | |
| 30 | - = f.label :password | |
| 31 | - .input= f.password_field :password, disabled: f.object.force_random_password | |
| 32 | - .clearfix | |
| 33 | - = f.label :password_confirmation | |
| 34 | - .input= f.password_field :password_confirmation, disabled: f.object.force_random_password | |
| 35 | - -if f.object.new_record? | |
| 27 | + - if @admin_user.new_record? | |
| 28 | + %fieldset | |
| 29 | + %legend Password | |
| 30 | + .clearfix | |
| 31 | + = f.label :password | |
| 32 | + .input | |
| 33 | + %strong | |
| 34 | + A temporary password will be generated and sent to user. | |
| 35 | + %br | |
| 36 | + User will be forced to change it after first sign in | |
| 37 | + - else | |
| 38 | + %fieldset | |
| 39 | + %legend Password | |
| 40 | + .clearfix | |
| 41 | + = f.label :password | |
| 42 | + .input= f.password_field :password, disabled: f.object.force_random_password | |
| 36 | 43 | .clearfix |
| 37 | - = f.label :force_random_password do | |
| 38 | - %span Generate random password | |
| 39 | - .input= f.check_box :force_random_password, {}, true, nil | |
| 44 | + = f.label :password_confirmation | |
| 45 | + .input= f.password_field :password_confirmation, disabled: f.object.force_random_password | |
| 40 | 46 | |
| 41 | 47 | %fieldset |
| 42 | 48 | %legend Access | ... | ... |
app/views/admin/users/show.html.haml
| 1 | +%h3.page_title | |
| 2 | + User: | |
| 3 | + = @admin_user.name | |
| 4 | + - if @admin_user.blocked? | |
| 5 | + %span.cred (Blocked) | |
| 6 | + - if @admin_user.admin | |
| 7 | + %span.cred (Admin) | |
| 8 | + | |
| 9 | + .pull-right | |
| 10 | + = link_to edit_admin_user_path(@admin_user), class: "btn grouped btn-small" do | |
| 11 | + %i.icon-edit | |
| 12 | + Edit | |
| 13 | + - unless @admin_user == current_user | |
| 14 | + - if @admin_user.blocked? | |
| 15 | + = link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn grouped btn-small success" | |
| 16 | + - else | |
| 17 | + = link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn grouped btn-small btn-remove" | |
| 18 | + = link_to 'Destroy', [:admin, @admin_user], confirm: "USER #{@admin_user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn grouped btn-small btn-remove" | |
| 19 | +%hr | |
| 20 | + | |
| 1 | 21 | .row |
| 2 | 22 | .span6 |
| 3 | - %h3.page_title | |
| 4 | - = image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90" | |
| 5 | - = @admin_user.name | |
| 6 | - - if @admin_user.blocked? | |
| 7 | - %span.cred (Blocked) | |
| 8 | - - if @admin_user.admin | |
| 9 | - %span.cred (Admin) | |
| 10 | - .pull-right | |
| 11 | - = link_to edit_admin_user_path(@admin_user), class: "btn pull-right" do | |
| 12 | - %i.icon-edit | |
| 13 | - Edit | |
| 14 | - %br | |
| 15 | - %small @#{@admin_user.username} | |
| 16 | - %br | |
| 17 | - %small member since #{@admin_user.created_at.stamp("Nov 12, 2031")} | |
| 18 | - .clearfix | |
| 19 | - %hr | |
| 20 | - %p | |
| 21 | - %span.btn.btn-small | |
| 22 | - %i.icon-envelope | |
| 23 | - = mail_to @admin_user.email | |
| 24 | - - unless @admin_user == current_user | |
| 25 | - - if @admin_user.blocked? | |
| 26 | - = link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small success" | |
| 27 | - - else | |
| 28 | - = link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" | |
| 29 | - = link_to 'Destroy', [:admin, @admin_user], confirm: "USER #{@admin_user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove" | |
| 23 | + .ui-box | |
| 24 | + %h5.title | |
| 25 | + Account: | |
| 26 | + .pull-right | |
| 27 | + = image_tag gravatar_icon(@admin_user.email, 32), class: "avatar s32" | |
| 28 | + %ul.well-list | |
| 29 | + %li | |
| 30 | + %span.light Name: | |
| 31 | + %strong= @admin_user.name | |
| 32 | + %li | |
| 33 | + %span.light Username: | |
| 34 | + %strong | |
| 35 | + = @admin_user.username | |
| 36 | + %li | |
| 37 | + %span.light Email: | |
| 38 | + %strong | |
| 39 | + = mail_to @admin_user.email | |
| 40 | + | |
| 41 | + %li | |
| 42 | + %span.light Member since: | |
| 43 | + %strong | |
| 44 | + = @admin_user.created_at.stamp("Nov 12, 2031") | |
| 45 | + | |
| 46 | + %li | |
| 47 | + %span.light Last sign-in at: | |
| 48 | + %strong | |
| 49 | + = @admin_user.last_sign_in_at.stamp("Nov 12, 2031") | |
| 50 | + | |
| 51 | + - if @admin_user.ldap_user? | |
| 52 | + %li | |
| 53 | + %span.light LDAP uid: | |
| 54 | + %strong | |
| 55 | + = @admin_user.extern_uid | |
| 56 | + | |
| 57 | + - if @admin_user.created_by | |
| 58 | + %li | |
| 59 | + %span.light Created by: | |
| 60 | + %strong | |
| 61 | + = link_to @admin_user.created_by.name, [:admin, @admin_user.created_by] | |
| 62 | + | |
| 30 | 63 | %hr |
| 31 | 64 | %h5 |
| 32 | 65 | Add User to Projects |
| ... | ... | @@ -67,11 +100,11 @@ |
| 67 | 100 | |
| 68 | 101 | |
| 69 | 102 | .span6 |
| 70 | - = render 'users/profile', user: @admin_user | |
| 71 | 103 | .ui-box |
| 72 | 104 | %h5.title Projects (#{@projects.count}) |
| 73 | 105 | %ul.well-list |
| 74 | 106 | - @projects.sort_by(&:name_with_namespace).each do |project| |
| 107 | + - tm = project.team.get_tm(@admin_user.id) | |
| 75 | 108 | %li |
| 76 | 109 | = link_to admin_project_path(project), class: dom_class(project) do |
| 77 | 110 | - if project.namespace |
| ... | ... | @@ -79,16 +112,17 @@ |
| 79 | 112 | \/ |
| 80 | 113 | %strong.well-title |
| 81 | 114 | = truncate(project.name, length: 45) |
| 82 | - %span.pull-right.light | |
| 83 | - - if project.owner == @admin_user | |
| 84 | - %i.icon-wrench | |
| 85 | - - tm = project.team.get_tm(@admin_user.id) | |
| 86 | - - if tm | |
| 87 | - = tm.project_access_human | |
| 88 | - = link_to edit_admin_project_member_path(project, tm.user), class: "btn btn-small" do | |
| 115 | + | |
| 116 | + - if project.owner == @admin_user | |
| 117 | + %span.label.label-info owner | |
| 118 | + | |
| 119 | + - if tm | |
| 120 | + .pull-right | |
| 121 | + = link_to edit_admin_project_member_path(project, tm.user), class: "btn grouped btn-small" do | |
| 89 | 122 | %i.icon-edit |
| 90 | - = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @admin_user), method: :delete, class: "btn btn-small btn-remove" do | |
| 123 | + = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @admin_user), method: :delete, class: "btn grouped btn-small btn-remove" do | |
| 91 | 124 | %i.icon-remove |
| 92 | - %p.light | |
| 93 | - %i.icon-wrench | |
| 94 | - – user is a project owner | |
| 125 | + | |
| 126 | + .pull-right.light | |
| 127 | + = tm.project_access_human | |
| 128 | + | ... | ... |
app/views/notify/new_user_email.html.haml
| ... | ... | @@ -8,13 +8,14 @@ |
| 8 | 8 | %p |
| 9 | 9 | login.......................................... |
| 10 | 10 | %code= @user['email'] |
| 11 | -%p | |
| 12 | - - unless Gitlab.config.gitlab.signup_enabled | |
| 11 | + | |
| 12 | +- if @user.created_by_id | |
| 13 | + %p | |
| 13 | 14 | password.................................. |
| 14 | 15 | %code= @password |
| 15 | 16 | |
| 16 | -%p | |
| 17 | - Please change your password immediately after login. | |
| 17 | + %p | |
| 18 | + You will be forced to change this password immediately after login. | |
| 18 | 19 | |
| 19 | 20 | %p |
| 20 | 21 | = link_to "Click here to login", root_url | ... | ... |
app/views/notify/new_user_email.text.erb
| ... | ... | @@ -3,10 +3,11 @@ Hi <%= @user.name %>! |
| 3 | 3 | The Administrator created an account for you. Now you are a member of company GitLab application. |
| 4 | 4 | |
| 5 | 5 | login.................. <%= @user.email %> |
| 6 | -<% unless Gitlab.config.gitlab.signup_enabled %> | |
| 6 | +<% if @user.created_by_id %> | |
| 7 | 7 | password............... <%= @password %> |
| 8 | + | |
| 9 | + You will be forced to change this password immediately after login. | |
| 8 | 10 | <% end %> |
| 9 | 11 | |
| 10 | -Please change your password immediately after login. | |
| 11 | 12 | |
| 12 | 13 | Click here to login: <%= url_for(root_url) %> | ... | ... |
db/schema.rb
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | # |
| 12 | 12 | # It's strongly recommended to check this file into your version control system. |
| 13 | 13 | |
| 14 | -ActiveRecord::Schema.define(:version => 20130613165816) do | |
| 14 | +ActiveRecord::Schema.define(:version => 20130613173246) do | |
| 15 | 15 | |
| 16 | 16 | create_table "deploy_keys_projects", :force => true do |t| |
| 17 | 17 | t.integer "deploy_key_id", :null => false |
| ... | ... | @@ -293,6 +293,7 @@ ActiveRecord::Schema.define(:version => 20130613165816) do |
| 293 | 293 | t.integer "color_scheme_id", :default => 1, :null => false |
| 294 | 294 | t.integer "notification_level", :default => 1, :null => false |
| 295 | 295 | t.datetime "password_expires_at" |
| 296 | + t.integer "created_by_id" | |
| 296 | 297 | end |
| 297 | 298 | |
| 298 | 299 | add_index "users", ["admin"], :name => "index_users_on_admin" | ... | ... |
spec/features/admin/admin_users_spec.rb
| ... | ... | @@ -20,13 +20,10 @@ describe "Admin::Users" do |
| 20 | 20 | |
| 21 | 21 | describe "GET /admin/users/new" do |
| 22 | 22 | before do |
| 23 | - @password = "123ABC" | |
| 24 | 23 | visit new_admin_user_path |
| 25 | 24 | fill_in "user_name", with: "Big Bang" |
| 26 | 25 | fill_in "user_username", with: "bang" |
| 27 | 26 | fill_in "user_email", with: "bigbang@mail.com" |
| 28 | - fill_in "user_password", with: @password | |
| 29 | - fill_in "user_password_confirmation", with: @password | |
| 30 | 27 | end |
| 31 | 28 | |
| 32 | 29 | it "should create new user" do |
| ... | ... | @@ -57,26 +54,13 @@ describe "Admin::Users" do |
| 57 | 54 | end |
| 58 | 55 | |
| 59 | 56 | it "should send valid email to user with email & password" do |
| 60 | - Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) | |
| 61 | 57 | User.observers.enable :user_observer do |
| 62 | 58 | click_button "Create user" |
| 63 | 59 | user = User.last |
| 64 | 60 | email = ActionMailer::Base.deliveries.last |
| 65 | 61 | email.subject.should have_content("Account was created") |
| 66 | 62 | email.text_part.body.should have_content(user.email) |
| 67 | - email.text_part.body.should have_content(@password) | |
| 68 | - end | |
| 69 | - end | |
| 70 | - | |
| 71 | - it "should send valid email to user with email without password when signup is enabled" do | |
| 72 | - Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) | |
| 73 | - User.observers.enable :user_observer do | |
| 74 | - click_button "Create user" | |
| 75 | - user = User.last | |
| 76 | - email = ActionMailer::Base.deliveries.last | |
| 77 | - email.subject.should have_content("Account was created") | |
| 78 | - email.text_part.body.should have_content(user.email) | |
| 79 | - email.text_part.body.should_not have_content(@password) | |
| 63 | + email.text_part.body.should have_content('password') | |
| 80 | 64 | end |
| 81 | 65 | end |
| 82 | 66 | end | ... | ... |