# Copyright (C) 2021-2030 Baidu Ltd.
#
# Author: dudeli<dudeli@baidu.com>
#
# This file is part of cloud-init. See LICENSE file for license information.

"""
Reset Password
-------------
**Summary:** Reset user password

Reset password for user if necessary.This a function for baidu cloud custom.

**Internal name:** ``cc_reset_password``

**Module frequency:** per always

**Supported distros:** all

**Config keys**::

    resetpasswd: user:password
"""

import re
import os

from cloudinit import log as logging
from cloudinit import util
from cloudinit.settings import PER_ALWAYS

frequency = PER_ALWAYS

LOG = logging.getLogger(__name__)


def read_prev_password(filename):
    """
    read previous password from filename

    Args:
    filename: filename string

    Returns:
    string contains password
    """
    try:
        password = util.load_file(filename)
    except IOError:
        password = ""
    return password


def handle(_name, cfg, cloud, log, args):
    """
    handle reset password module

    Args:
    _name: module name
    cfg: cloud config
    cloud: cloudinit object wrapper
    log: logger
    args: extra args

    Returns:
    """
    if 'resetpasswd' not in cfg:
        log.debug(("Skipping module named %s,"
                   " no 'resetpasswd' key in configuration"), _name)
        return
    else:
        password = util.get_cfg_option_str(cfg, "resetpasswd", None)

    prev_fn = os.path.join(cloud.get_cpath('data'), "previous-password")
    prev_password = read_prev_password(prev_fn)

    if not password:
        if prev_password:
            password = prev_password
            log.debug(
                'No password found in configuration, use previous password.')
        else:
            log.warn("No password specified, abort.")
            return
    elif password and password == prev_password:
        log.debug("New password is the same as previous, skip reset.")
        return

    prog = re.compile(r'\$[1,2a,2y,5,6](\$.+){2}')
    u, p = password.split(':', 1)
    hashed = ''
    if prog.match(p) is not None and ":" not in p:
        hashed = '-e'

    try:
        log.debug("Resetting password for %s:", u)
        util.subp(['chpasswd', hashed], password)
    except Exception as e:
        util.logexc(
            log, "Failed to reset passwords with chpasswd for %s", u)
        raise e
    else:
        util.write_file(prev_fn, password, '0644')

# vi: ts=4 expandtab
