#!/usr/bin/python
"""
Change users shell, chat or mail password.
"""

import os,pwd,getpass

from systematic.shell import Script
from secrets.config import SecretsConfig,SecretsConfigError
from secrets.password import PasswordService,PasswordServiceError

script = Script()
script.add_argument('-l','--list',action='store_true',help='List available password types')
script.add_argument('-s','--service',action='append',help='Service to change password for')
script.add_argument('-u','--other-user',action='store_true',help='Change password for other user')
script.add_argument('-C','--config',help='Configuration file path')
script.add_argument('-A','--all',action='store_true',help='Change all passwords')
script.add_argument('users',nargs='*',help='Usernames to process')
args = script.parse_args()

def ask_password(service,user,verify=False,old=None):
    """
    Function to ask for passwords with getpass
    """
    password = None
    if old is None and verify is False:
        label = 'Enter %s password for %s: ' % (service,user)
        password = getpass.getpass(label)
        if '\x03' in password:
            script.exit(1,'Interrupted')
        return password

    l1 = 'Enter new %s password for %s: ' % (service,user)
    l2 = 'Confirm new %s password for %s: ' % (service,user)
    while True:
        password = getpass.getpass(l1)
        if '\x03' in password:
            script.exit(1,'Interrupted')
        confirm = getpass.getpass(l2)
        if '\x03' in confirm:
            script.exit(1,'Interrupted')
        if old is not None and old==password:
            print "Password is same as current password, please try again."
        elif password!=confirm:
            print "Passwords don't match, please try again."
        else:
            break
    return password

try:
    pwc = SecretsConfig(args.config)
except SecretsConfigError,emsg:
    pwc = None
    script.exit(1,emsg)

if args.list:
    for s in pwc.values():
        print '%-12s %s' % (s.name,s.description)
    script.exit(0)

if args.all or len(pwc.values())==1:
    services = [PasswordService(s) for s in pwc.values()]
else:
    services = []
    if args.service is None:
        script.exit(1,'Choose service for which to change password')
    for s in args.service:
        if s not in pwc.keys():
            script.exit(1,'Invalid service name: %s' % s)
        services.append(PasswordService(pwc[s]))

admin = os.geteuid()==0 and True or False
if args.other_user:
    admin = True

if admin:
    if not len(args.users):
        script.exit(1,'Give accounts to modify as arguments')
    for username in args.users:
        for service in services:
            password = pwc.get_cached_admin_password(service.server)
            if not password:
                while True:
                    password = ask_password('admin',service.admin_dn)
                    if not service.test_password(service.admin_dn,password,admin=True):
                        print 'Invalid password'
                        continue
                    pwc.set_cached_admin_password(service.server,password)
                    break
            user_pass = ask_password(service.name,username,verify=True,old=None)
            try:
                service.change_password(username,user_pass,password,admin=True)
                script.log.info('Successfully changed %s password for %s' % (service.name,username))
            except PasswordServiceError,emsg:
                print 'ERROR changing password: %s' % emsg
else:
    username = pwd.getpwuid(os.geteuid()).pw_name
    for service in services:
        while True:
            old = ask_password(service.name,username,verify=False)
            if not service.test_password(username,old):
                print 'Invalid password'
                continue
            new = ask_password(service.name,username,verify=True,old=old)
            try:
                service.change_password(username,new,old,admin=False)
                script.log.info('Successfully changed %s password for %s' % ( service.name, username ))
                break
            except PasswordServiceError,emsg:
                print 'ERROR changing password: %s' % emsg

script.exit(0)

