|
|
#-*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
import os
|
|
|
import sys
|
|
|
# Ввод pwd
|
|
|
import getpass
|
|
|
import types
|
|
|
from cl_utils import removeDir
|
|
|
from cl_print import color_print
|
|
|
from server.share import servicesAPI
|
|
|
from server.utils import rawInput, isCorrectStringNet, addInfoUser, addInfoGroup, dialogYesNo
|
|
|
# Перевод модуля
|
|
|
import cl_lang
|
|
|
tr = cl_lang.lang()
|
|
|
tr.setLocalDomain('cl_lib')
|
|
|
tr.setLanguage(sys.modules[__name__])
|
|
|
import cl_overriding
|
|
|
|
|
|
class users(color_print):
|
|
|
"""Общие методы для серверных программ,
|
|
|
|
|
|
(работа с пользователями и группами)"""
|
|
|
|
|
|
# Объект с методами доступа к другим сервисам
|
|
|
servicesAPIObj = servicesAPI()
|
|
|
|
|
|
# Статические группы
|
|
|
staticGroups = {\
|
|
|
'client':addInfoGroup('client',
|
|
|
'900',
|
|
|
'Client group',
|
|
|
'2801',
|
|
|
'2'),
|
|
|
'Domain Admins':addInfoGroup('Domain Admins',
|
|
|
'512',
|
|
|
'Domain Administrators',
|
|
|
'512',
|
|
|
'2'),
|
|
|
'Domain Users':addInfoGroup('Domain Users',
|
|
|
'513',
|
|
|
'Domain Users',
|
|
|
'513',
|
|
|
'2'),
|
|
|
'Domain Guests':addInfoGroup('Domain Guests',
|
|
|
'514',
|
|
|
'Domain Guests Users',
|
|
|
'514',
|
|
|
'2'),
|
|
|
'Domain Computers':addInfoGroup('Domain Computers',
|
|
|
'515',
|
|
|
'Domain Computers accounts',
|
|
|
'515',
|
|
|
'2'),
|
|
|
'Administrators':addInfoGroup('Administrators',
|
|
|
'544',
|
|
|
'Domain Members can fully \
|
|
|
administer the computer/sambaDomainName',
|
|
|
'544',
|
|
|
'5',
|
|
|
"S-1-5-32-544"),
|
|
|
'Account Operators':addInfoGroup('Account Operators',
|
|
|
'548',
|
|
|
'Domain Users to manipulate \
|
|
|
users accounts',
|
|
|
'548',
|
|
|
'5',
|
|
|
"S-1-5-32-548"),
|
|
|
'System Operators':addInfoGroup('System Operators',
|
|
|
'549',
|
|
|
'Domain System Operators',
|
|
|
'549',
|
|
|
'5',
|
|
|
"S-1-5-32-549"),
|
|
|
'Print Operators':addInfoGroup('Print Operators',
|
|
|
'550',
|
|
|
'Domain Print Operators',
|
|
|
'550',
|
|
|
'5',
|
|
|
"S-1-5-32-550"),
|
|
|
'Backup Operators':addInfoGroup('Backup Operators',
|
|
|
'551',
|
|
|
'Domain Members can bypass \
|
|
|
file security to back up files',
|
|
|
'551',
|
|
|
'5',
|
|
|
"S-1-5-32-551"),
|
|
|
'Replicators':addInfoGroup('Replicators',
|
|
|
'552',
|
|
|
'Domain Supports file replication \
|
|
|
in a sambaDomainName',
|
|
|
'552',
|
|
|
'5',
|
|
|
"S-1-5-32-552"),
|
|
|
}
|
|
|
# Статические пользователи
|
|
|
staticUsers = {\
|
|
|
'client':addInfoUser('client',
|
|
|
'900',
|
|
|
'900',
|
|
|
'Client samba user'),
|
|
|
'admin':addInfoUser('admin',
|
|
|
'901',
|
|
|
'544',
|
|
|
'Admin samba user')}
|
|
|
|
|
|
def getUserUidAndGid(self, userName, groupName=""):
|
|
|
"""Находит в системе uid и gid пользователя
|
|
|
|
|
|
userName - имя пользователя и имя группы пользователя
|
|
|
"""
|
|
|
if not groupName:
|
|
|
groupName = userName
|
|
|
import pwd
|
|
|
try:
|
|
|
uid = pwd.getpwnam(userName)[2]
|
|
|
except:
|
|
|
self.printERROR(_("Can not found user %s in this system")%userName)
|
|
|
return ()
|
|
|
try:
|
|
|
import grp
|
|
|
gid = grp.getgrnam(groupName)[2]
|
|
|
except:
|
|
|
self.printERROR(_("Can not found group %s in this system")\
|
|
|
%groupName)
|
|
|
return ()
|
|
|
return (uid, gid)
|
|
|
|
|
|
|
|
|
def __restoreDelUser(self,userName,service,srcDir,message,unixObj=False):
|
|
|
"""Возвращаем данные удаленного пользователя"""
|
|
|
# Ищем Unix пользователя
|
|
|
searchUnixUser = self.servicesAPIObj.searchUnixUser(userName, unixObj)
|
|
|
# id пользователя
|
|
|
strUid = ""
|
|
|
if searchUnixUser:
|
|
|
strUid = searchUnixUser[0][0][1]['uidNumber'][0]
|
|
|
else:
|
|
|
resPasswd = self.servicesAPIObj.searchPasswdUser(userName, unixObj)
|
|
|
if resPasswd:
|
|
|
strUid = resPasswd.split(":")[2]
|
|
|
if strUid:
|
|
|
delBackDir =\
|
|
|
os.path.join(self.clVars.Get("sr_deleted_path"),
|
|
|
"%s-%s"%(userName,strUid),
|
|
|
service)
|
|
|
if strUid and os.path.exists(delBackDir) and os.listdir(delBackDir):
|
|
|
if message == None or type(message) == types.BooleanType:
|
|
|
dialogRes = message
|
|
|
else:
|
|
|
dialogRes = dialogYesNo(message)
|
|
|
if dialogRes and dialogRes == True:
|
|
|
try:
|
|
|
copyDir(srcDir, delBackDir)
|
|
|
except:
|
|
|
self.printERROR(_("Not restore user data in dir %s")\
|
|
|
%srcDir)
|
|
|
return False
|
|
|
self.printSUCCESS(_("Restore user data in dir %s")\
|
|
|
%srcDir)
|
|
|
return "Yes", delBackDir
|
|
|
elif dialogRes == False:
|
|
|
return "No", delBackDir
|
|
|
elif dialogRes == None:
|
|
|
return "Cancel", delBackDir
|
|
|
return True
|
|
|
|
|
|
def restorePathDelUser(self,userName,destDir,relDir,message,unixObj=False):
|
|
|
"""Восстанавливает директорию удаленного пользователя"""
|
|
|
removedDir = False
|
|
|
flagError = False
|
|
|
resRestore = self.__restoreDelUser(userName, relDir,
|
|
|
destDir, message, unixObj)
|
|
|
# Если ошибка то выходим
|
|
|
if not resRestore:
|
|
|
flagError = True
|
|
|
# Флаг создания директории профиля пользователя
|
|
|
createDir = destDir
|
|
|
term = ""
|
|
|
if resRestore == True:
|
|
|
term = message
|
|
|
if not flagError and type(resRestore) == types.TupleType:
|
|
|
# Если cansel
|
|
|
if resRestore[0] == "Cancel":
|
|
|
# Удаляем пользователя
|
|
|
flagError = True
|
|
|
term = None
|
|
|
# Если No
|
|
|
elif resRestore[0] == "No":
|
|
|
try:
|
|
|
removeDir(resRestore[1])
|
|
|
except:
|
|
|
flagError = True
|
|
|
if not flagError:
|
|
|
removedDir = resRestore[1]
|
|
|
term = False
|
|
|
elif resRestore[0] == "Yes":
|
|
|
createDir = False
|
|
|
removedDir = resRestore[1]
|
|
|
term = True
|
|
|
if flagError or term == "":
|
|
|
return False
|
|
|
else:
|
|
|
return (term, createDir, removedDir)
|
|
|
|
|
|
|
|
|
def backupDelUser(self, userName, service, srcDir, unixObj=False):
|
|
|
"""Сохраняем данные удаляемого пользователя"""
|
|
|
# Ищем Unix пользователя
|
|
|
searchUnixUser = self.servicesAPIObj.searchUnixUser(userName, unixObj)
|
|
|
# id пользователя
|
|
|
strUid = ""
|
|
|
if searchUnixUser:
|
|
|
strUid = searchUnixUser[0][0][1]['uidNumber'][0]
|
|
|
if strUid:
|
|
|
delBackDir =\
|
|
|
os.path.join(self.clVars.Get("sr_deleted_path"),
|
|
|
"%s-%s"%(userName,strUid),
|
|
|
service)
|
|
|
if os.path.exists(delBackDir) and os.listdir(delBackDir):
|
|
|
self.printERROR(_("Found deleted user data dir %s")\
|
|
|
%delBackDir)
|
|
|
self.printERROR(_("Not created deleted user data dir %s")\
|
|
|
%delBackDir)
|
|
|
return False
|
|
|
else:
|
|
|
delBackDir =\
|
|
|
os.path.join(self.clVars.Get("sr_deleted_path"),
|
|
|
"%s"%(userName),
|
|
|
service)
|
|
|
i = 0
|
|
|
while os.path.exists(delBackDir):
|
|
|
i += 1
|
|
|
delBackDir =\
|
|
|
os.path.join(self.clVars.Get("sr_deleted_path"),
|
|
|
"%s_%s"%(userName,i),
|
|
|
service)
|
|
|
# Cоздаем директорию хранения удаленных пользователей
|
|
|
if not os.path.exists(self.clVars.Get("sr_deleted_path")):
|
|
|
os.makedirs(self.clVars.Get("sr_deleted_path"))
|
|
|
#Делаем сохранение директории
|
|
|
try:
|
|
|
copyDir(delBackDir,srcDir)
|
|
|
except:
|
|
|
self.printERROR(_("Can not copy deleted user data in dir %s")\
|
|
|
%delBackDir)
|
|
|
return False
|
|
|
self.printSUCCESS(_("Created deleted user data dir %s")\
|
|
|
%delBackDir)
|
|
|
return True
|
|
|
|
|
|
def removeEmptyDir(self, rmDir):
|
|
|
"""Удаление пустых директорий"""
|
|
|
if not os.path.exists(rmDir):
|
|
|
self.printERROR(_("Not found remove dir %s") %rmDir)
|
|
|
return False
|
|
|
rDir = rmDir
|
|
|
while os.listdir(rDir) == []:
|
|
|
os.rmdir(rDir)
|
|
|
rDir = os.path.split(rDir)[0]
|
|
|
if rDir == "/":
|
|
|
break
|
|
|
return True
|
|
|
|
|
|
def createUserDir(self, uid, gid, userDir, mode=0700):
|
|
|
"""Создание пользовательской директории"""
|
|
|
if not os.path.exists(userDir):
|
|
|
os.makedirs(userDir)
|
|
|
if mode:
|
|
|
os.chmod(userDir,mode)
|
|
|
os.chown(userDir,uid,gid)
|
|
|
return True
|
|
|
else:
|
|
|
self.printERROR(_("Path %s exists") %userDir)
|
|
|
return False
|
|
|
|
|
|
def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644):
|
|
|
"""Создает пользовательский файл с содержимым
|
|
|
|
|
|
Если директория файла не существует то ошибка
|
|
|
"""
|
|
|
userDir = os.path.split(fileName)[0]
|
|
|
if not os.path.exists(userDir):
|
|
|
self.printERROR(_("Path %s not exists") %userDir)
|
|
|
return False
|
|
|
fd = os.open(fileName, os.O_CREAT)
|
|
|
os.close(fd)
|
|
|
os.chmod(fileName, mode)
|
|
|
os.chown(fileName,uid,gid)
|
|
|
if fileTxt:
|
|
|
FD = open(fileName, "r+")
|
|
|
FD.write(fileTxt)
|
|
|
FD.close()
|
|
|
return True
|
|
|
|
|
|
def getUserAllowNetwork(self, strPrompt, strNetAllow):
|
|
|
"""Получаем от пользователя доверительные сети
|
|
|
|
|
|
вывод - список доверительных сетей
|
|
|
"""
|
|
|
def printW():
|
|
|
cl_overriding.printSUCCESS(_("Incorrect string allow networks"))
|
|
|
cl_overriding.printSUCCESS(\
|
|
|
_("Example - allow networks: 10.0.0.0/24 10.0.10.0/24"))
|
|
|
cl_overriding.printSUCCESS(_("Try again\n"))
|
|
|
strNet = rawInput(strPrompt, strNetAllow)
|
|
|
i = 0
|
|
|
while i<3 and not isCorrectStringNet(strNet):
|
|
|
printW()
|
|
|
strNet = rawInput(strPrompt, strNet)
|
|
|
i +=1
|
|
|
if i == 3 and not isCorrectStringNet(strNet):
|
|
|
printW()
|
|
|
self.printERROR(_("You used four attempts, \
|
|
|
if you want to continue to run the program again"))
|
|
|
return False
|
|
|
return isCorrectStringNet(strNet)
|