#!/usr/bin/python3
# -*- mode: python -*-

#   Copyright (c) 1999-2000  Jason Gunthorpe <jgg@debian.org>
#   Copyright (c) 2001-2003  James Troup <troup@debian.org>
#   Copyright (c) 2004-2005  Joey Schulze <joey@infodrom.org>
#   Copyright (c) 2007,2008 Peter Palfrader <peter@palfrader.org>
#
#   This program 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 2 of the License, or
#   (at your option) any later version.
#
#   This program 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 this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

from __future__ import print_function

import getopt
import os
import pwd
import sys
import time

import ldap
from six.moves import input

from userdir_ldap.ldap import (
    BaseDn, GetAttr, passwdAccessLDAP, Group2GID, RoleObjectClasses)


# This tries to search for a free UID. There are two possible ways to do
# this, one is to fetch all the entires and pick the highest, the other
# is to randomly guess uids until one is free. This uses the former.
# Regrettably ldap doesn't have an integer attribute comparision function
# so we can only cut the search down slightly

# [JT] This is broken with Woody LDAP and the Schema; for now just
#      search through all UIDs.
def GetFreeID(ldapconn):
   Attrs = ldapconn.search_s(BaseDn, ldap.SCOPE_ONELEVEL,
                             "uidNumber=*", ["uidNumber"])
   HighestUID = 0
   for attr in Attrs:
      ID = int(GetAttr(attr, "uidNumber", "0"))
      if ID > HighestUID:
         HighestUID = ID
   return HighestUID + 1


# Main starts here
AdminUser = pwd.getpwuid(os.getuid())[0]

# Process options
(options, arguments) = getopt.getopt(sys.argv[1:], "u:")
for (switch, val) in options:
   if (switch == '-u'):
      AdminUser = val

lc = passwdAccessLDAP(BaseDn, AdminUser)

while 1:
   account = input("Who are you going to add? ")
   if account == "":
      sys.exit(0)

   Attrs = lc.search_s(BaseDn, ldap.SCOPE_ONELEVEL, "uid=" + account)
   if len(Attrs) == 0:
      break

   print("That account already exists.")

Res = input("Name for GECOS field? ")
if Res != "":
   cn = Res

# GID
Res = input("Group name? ")
if Res != "":
   gidNumber = Group2GID(lc, Res)
   if gidNumber == -1:
      print("Can't figure out which gid %s is" % Res)
      sys.exit(1)

# UID
uidNumber = GetFreeID(lc)

# Now we have all the bits of information.
print("------------")
print("Final information collected:")
print(" Username %s:" % cn)
print("   Assigned UID:", uidNumber, " GID:", gidNumber)
print("   GECOS Field: \"%s,,,,\"" % cn)
print("   Login Shell: /bin/false")
Res = input("Continue [No/yes]? ")
if Res != "yes":
   print("Not adding %s" % cn)
   sys.exit(1)

# Submit the modification request
Dn = "uid=" + account + "," + BaseDn
print("Updating LDAP directory..", end="")
sys.stdout.flush()

Details = [("uid", account.encode("utf-8")),
           ("objectClass", [c.encode("utf-8") for c in RoleObjectClasses]),
           ("uidNumber", str(uidNumber).encode("ascii")),
           ("gidNumber", str(gidNumber).encode("ascii")),
           ("gecos", cn.encode("utf-8") + b",,,,"),
           ("loginShell", b"/bin/false"),
           ("cn", cn.encode("utf-8")),
           ("shadowLastChange", str(int(time.time() / 24 / 60 / 60)).encode("utf-8")),
           ("shadowMin", b"0"),
           ("shadowMax", b"99999"),
           ("shadowWarning", b"7"),
           ("userPassword", b"{crypt}*")]
lc.add_s(Dn, Details)

print()
