# test code for the win_user module
# (c) 2014, Chris Church <chris@ninemoreminutes.com>

# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

- name: remove existing test user if present
  win_user: name="{{ test_win_user_name }}" state="absent"
  register: win_user_remove_result

- name: check user removal result
  assert:
    that:
      - "win_user_remove_result.name"
      - "win_user_remove_result.state == 'absent'"

- name: try to remove test user again
  win_user: name="{{ test_win_user_name }}" state="absent"
  register: win_user_remove_result_again

- name: check user removal result again
  assert:
    that:
      - "win_user_remove_result_again is not changed"
      - "win_user_remove_result_again.name"
      - "win_user_remove_result_again.msg"
      - "win_user_remove_result.state == 'absent'"

- name: test missing user with query state
  win_user: name="{{ test_win_user_name }}" state="query"
  register: win_user_missing_query_result

- name: check missing query result
  assert:
    that:
      - "win_user_missing_query_result is not changed"
      - "win_user_missing_query_result.name"
      - "win_user_missing_query_result.msg"
      - "win_user_missing_query_result.state == 'absent'"

- name: test create user
  win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password }}" fullname="Test User" description="Test user account" groups="Guests"
  register: win_user_create_result

- name: check user creation result
  assert:
    that:
      - "win_user_create_result is changed"
      - "win_user_create_result.name == '{{ test_win_user_name }}'"
      - "win_user_create_result.fullname == 'Test User'"
      - "win_user_create_result.description == 'Test user account'"
      - "win_user_create_result.path"
      - "win_user_create_result.state == 'present'"

- name: update user full name and description
  win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible" groups=""
  register: win_user_update_result

- name: check full name and description update result
  assert:
    that:
      - "win_user_update_result is changed"
      - "win_user_update_result.fullname == 'Test Ansible User'"
      - "win_user_update_result.description == 'Test user account created by Ansible'"

- name: update user full name and description again with same values
  win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible"
  register: win_user_update_result_again

- name: check full name and description result again
  assert:
    that:
      - "win_user_update_result_again is not changed"
      - "win_user_update_result_again.fullname == 'Test Ansible User'"
      - "win_user_update_result_again.description == 'Test user account created by Ansible'"

- name: test again with no options or changes
  win_user: name="{{ test_win_user_name }}"
  register: win_user_nochange_result

- name: check no changes result
  assert:
    that:
      - "win_user_nochange_result is not changed"

- name: test again with query state
  win_user: name="{{ test_win_user_name }}" state="query"
  register: win_user_query_result

- name: check query result
  assert:
    that:
      - "win_user_query_result is not changed"
      - "win_user_query_result.state == 'present'"
      - "win_user_query_result.name == '{{ test_win_user_name }}'"
      - "win_user_query_result.fullname == 'Test Ansible User'"
      - "win_user_query_result.description == 'Test user account created by Ansible'"
      - "win_user_query_result.path"
      - "win_user_query_result.sid"
      - "win_user_query_result.groups == []"

- name: change user password
  win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
  register: win_user_password_result

- name: check password change result
  assert:
    that:
      - "win_user_password_result is changed"

- name: change user password again to same value
  win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
  register: win_user_password_result_again

- name: check password change result again
  assert:
    that:
      - "win_user_password_result_again is not changed"

- name: check update_password=on_create for existing user
  win_user: name="{{ test_win_user_name }}" password="ThisP@ssW0rdShouldNotBeUsed" update_password=on_create
  register: win_user_nopasschange_result

- name: check password change with on_create flag result
  assert:
    that:
      - "win_user_nopasschange_result is not changed"

- name: set password expired flag
  win_user: name="{{ test_win_user_name }}" password_expired=yes
  register: win_user_password_expired_result

- name: check password expired result
  assert:
    that:
      - "win_user_password_expired_result is changed"
      - "win_user_password_expired_result.password_expired"

- name: set password when expired
  win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
  register: win_user_can_set_password_on_expired

- name: check set password on expired result
  assert:
    that:
      - win_user_can_set_password_on_expired is changed

- name: set password expired flag again
  win_user: name="{{ test_win_user_name }}" password_expired=yes
  register: win_user_password_expired_result

- name: check password expired result
  assert:
    that:
      - "win_user_password_expired_result is changed"
      - "win_user_password_expired_result.password_expired"

- name: clear password expired flag
  win_user: name="{{ test_win_user_name }}" password_expired=no
  register: win_user_clear_password_expired_result

- name: check clear password expired result
  assert:
    that:
      - "win_user_clear_password_expired_result is changed"
      - "not win_user_clear_password_expired_result.password_expired"

- name: set password never expires flag
  win_user: name="{{ test_win_user_name }}" password_never_expires=yes
  register: win_user_password_never_expires_result

- name: check password never expires result
  assert:
    that:
      - "win_user_password_never_expires_result is changed"
      - "win_user_password_never_expires_result.password_never_expires"

- name: clear password never expires flag
  win_user: name="{{ test_win_user_name }}" password_never_expires=no
  register: win_user_clear_password_never_expires_result

- name: check clear password never expires result
  assert:
    that:
      - "win_user_clear_password_never_expires_result is changed"
      - "not win_user_clear_password_never_expires_result.password_never_expires"

- name: set user cannot change password flag
  win_user: name="{{ test_win_user_name }}" user_cannot_change_password=yes
  register: win_user_cannot_change_password_result

- name: check user cannot change password result
  assert:
    that:
      - "win_user_cannot_change_password_result is changed"
      - "win_user_cannot_change_password_result.user_cannot_change_password"

- name: clear user cannot change password flag
  win_user: name="{{ test_win_user_name }}" user_cannot_change_password=no
  register: win_user_can_change_password_result

- name: check clear user cannot change password result
  assert:
    that:
      - "win_user_can_change_password_result is changed"
      - "not win_user_can_change_password_result.user_cannot_change_password"

- name: set account disabled flag
  win_user: name="{{ test_win_user_name }}" account_disabled=true
  register: win_user_account_disabled_result

- name: check account disabled result
  assert:
    that:
      - "win_user_account_disabled_result is changed"
      - "win_user_account_disabled_result.account_disabled"

- name: set password on disabled account
  win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
  register: win_user_can_set_password_on_disabled

- name: check set password on disabled result
  assert:
    that:
      - win_user_can_set_password_on_disabled is changed
      - win_user_can_set_password_on_disabled.account_disabled

- name: clear account disabled flag
  win_user: name="{{ test_win_user_name }}" account_disabled=false
  register: win_user_clear_account_disabled_result

- name: check clear account disabled result
  assert:
    that:
      - "win_user_clear_account_disabled_result is changed"
      - "not win_user_clear_account_disabled_result.account_disabled"

- name: attempt to set account locked flag
  win_user: name="{{ test_win_user_name }}" account_locked=yes
  register: win_user_set_account_locked_result
  ignore_errors: true

- name: verify that attempting to set account locked flag fails
  assert:
    that:
      - "win_user_set_account_locked_result is failed"
      - "win_user_set_account_locked_result is not changed"

- name: attempt to lockout test account
  script: lockout_user.ps1 "{{ test_win_user_name }}"

- name: get user to check if account locked flag is set
  win_user: name="{{ test_win_user_name }}" state="query"
  register: win_user_account_locked_result

- name: clear account locked flag if set
  win_user: name="{{ test_win_user_name }}" account_locked=no
  register: win_user_clear_account_locked_result
  when: "win_user_account_locked_result.account_locked"

- name: check clear account lockout result if account was locked
  assert:
    that:
      - "win_user_clear_account_locked_result is changed"
      - "not win_user_clear_account_locked_result.account_locked"
  when: "win_user_account_locked_result.account_locked"

- name: assign test user to a group
  win_user: name="{{ test_win_user_name }}" groups="Users"
  register: win_user_replace_groups_result

- name: check assign user to group result
  assert:
    that:
      - "win_user_replace_groups_result is changed"
      - "win_user_replace_groups_result.groups|length == 1"
      - "win_user_replace_groups_result.groups[0]['name'] == 'Users'"

- name: assign test user to the same group
  win_user:
    name: "{{ test_win_user_name }}"
    groups: ["Users"]
  register: win_user_replace_groups_again_result

- name: check assign user to group again result
  assert:
    that:
      - "win_user_replace_groups_again_result is not changed"

- name: add user to another group
  win_user: name="{{ test_win_user_name }}" groups="Power Users" groups_action="add"
  register: win_user_add_groups_result

- name: check add user to another group result
  assert:
    that:
      - "win_user_add_groups_result is changed"
      - "win_user_add_groups_result.groups|length == 2"
      - "win_user_add_groups_result.groups[0]['name'] in ('Users', 'Power Users')"
      - "win_user_add_groups_result.groups[1]['name'] in ('Users', 'Power Users')"

- name: add user to another group again
  win_user:
    name: "{{ test_win_user_name }}"
    groups: "Power Users"
    groups_action: add
  register: win_user_add_groups_again_result

- name: check add user to another group again result
  assert:
    that:
      - "win_user_add_groups_again_result is not changed"

- name: remove user from a group
  win_user: name="{{ test_win_user_name }}" groups="Users" groups_action="remove"
  register: win_user_remove_groups_result

- name: check remove user from group result
  assert:
    that:
      - "win_user_remove_groups_result is changed"
      - "win_user_remove_groups_result.groups|length == 1"
      - "win_user_remove_groups_result.groups[0]['name'] == 'Power Users'"

- name: remove user from a group again
  win_user:
    name: "{{ test_win_user_name }}"
    groups:
      - "Users"
    groups_action: remove
  register: win_user_remove_groups_again_result

- name: check remove user from group again result
  assert:
    that:
      - "win_user_remove_groups_again_result is not changed"

- name: reassign test user to multiple groups
  win_user: name="{{ test_win_user_name }}" groups="Users, Guests" groups_action="replace"
  register: win_user_reassign_groups_result

- name: check reassign user groups result
  assert:
    that:
      - "win_user_reassign_groups_result is changed"
      - "win_user_reassign_groups_result.groups|length == 2"
      - "win_user_reassign_groups_result.groups[0]['name'] in ('Users', 'Guests')"
      - "win_user_reassign_groups_result.groups[1]['name'] in ('Users', 'Guests')"

- name: reassign test user to multiple groups again
  win_user:
    name: "{{ test_win_user_name }}"
    groups:
      - "Users"
      - "Guests"
    groups_action: replace
  register: win_user_reassign_groups_again_result

- name: check reassign user groups again result
  assert:
    that:
      - "win_user_reassign_groups_again_result is not changed"

- name: remove user from all groups
  win_user: name="{{ test_win_user_name }}" groups=""
  register: win_user_remove_all_groups_result

- name: check remove user from all groups result
  assert:
    that:
      - "win_user_remove_all_groups_result is changed"
      - "win_user_remove_all_groups_result.groups|length == 0"

- name: remove user from all groups again
  win_user:
    name: "{{ test_win_user_name }}"
    groups: []
  register: win_user_remove_all_groups_again_result

- name: check remove user from all groups again result
  assert:
    that:
      - "win_user_remove_all_groups_again_result is not changed"

- name: assign user to invalid group
  win_user: name="{{ test_win_user_name }}" groups="Userz"
  register: win_user_invalid_group_result
  ignore_errors: true

- name: check invalid group result
  assert:
    that:
      - "win_user_invalid_group_result is failed"
      - "win_user_invalid_group_result.msg"
      - win_user_invalid_group_result.msg is match("group 'Userz' not found")

- name: remove test user when finished
  win_user: name="{{ test_win_user_name }}" state="absent"
  register: win_user_final_remove_result

- name: check final user removal result
  assert:
    that:
      - "win_user_final_remove_result is changed"
      - "win_user_final_remove_result.name"
      - "win_user_final_remove_result.msg"
      - "win_user_final_remove_result.state == 'absent'"

- name: test removed user with query state
  win_user: name="{{ test_win_user_name }}" state="query"
  register: win_user_removed_query_result

- name: check removed query result
  assert:
    that:
      - "win_user_removed_query_result is not changed"
      - "win_user_removed_query_result.name"
      - "win_user_removed_query_result.msg"
      - "win_user_removed_query_result.state == 'absent'"

# Tests the Test-Credential path where LogonUser fails if the user does not
# have the right for a network logon
- name: add new user that has the right SeDenyNetworkLogonRight
  win_user:
    name: '{{ test_win_user_name }}'
    password: '{{ test_win_user_password2 }}'
    state: present
    groups:
    - win_user-test

- name: add new user that has the right SeDenyNetworkLogonRight (idempotent)
  win_user:
    name: '{{ test_win_user_name }}'
    password: '{{ test_win_user_password2 }}'
    state: present
    groups:
    - win_user-test
  register: deny_network_idempotent

- name: assert add new user that has the right SeDenyNetworkLogonRight (idempotent)
  assert:
    that:
    - not deny_network_idempotent is changed
