25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

942 lines
34 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 Mir Calculate. http://www.calculate-linux.org
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from collections import namedtuple
  16. import sys
  17. from calculate.lib.utils.files import readLinesFile, listDirectory
  18. from calculate.ldap.ldap import Ldap
  19. from calculate.lib.utils.common import getPagesInterval
  20. import os
  21. from os import path
  22. import shutil
  23. _ = lambda x: x
  24. from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
  25. from calculate.lib.cl_ldap import ldap, LDAPConnectError, LDAPBadSearchFilter
  26. setLocalTranslate('cl_unix3', sys.modules[__name__])
  27. __ = getLazyLocalTranslate(_)
  28. class UnixError(Exception):
  29. pass
  30. UnixGroup = namedtuple("UnixGroup", ['group_name', 'gid', 'user_list',
  31. 'comment'])
  32. class GroupFile(object):
  33. def __init__(self, group_fn='/etc/group'):
  34. self.group_fn = group_fn
  35. def __iter__(self):
  36. for line in (x for x in readLinesFile(self.group_fn)
  37. if not x.startswith("#")):
  38. data = line.strip().split(':')[:4]
  39. if len(data) >= 4 and data[2].isdigit():
  40. yield UnixGroup(data[0], int(data[2]),
  41. filter(None, data[3].split(",")),
  42. "/etc/group")
  43. class UnixGroups(object):
  44. """
  45. Набор методов для нахождения параметров группы и сопаставления GID,
  46. названия
  47. """
  48. groups = GroupFile()
  49. exception = UnixError
  50. ldap_connect = None
  51. groups_dn = ""
  52. def __init__(self, ldap_connect, groups_dn):
  53. self.ldap_connect = ldap_connect
  54. self.groups_dn = groups_dn
  55. def search_system_group_name(self, name):
  56. for group in (x for x in self.groups if x.group_name == name):
  57. return group
  58. else:
  59. return None
  60. def search_system_group_id(self, gid):
  61. for group in (x for x in self.groups if x.gid == gid):
  62. return group
  63. else:
  64. return None
  65. def iterate_ldap_group(self, search_filter, offset=None, count=None):
  66. ldap_connect = self.ldap_connect
  67. if ldap_connect:
  68. base_dn = self.groups_dn
  69. if offset is not None:
  70. below = lambda x: x < offset
  71. else:
  72. below = lambda x: False
  73. if count is not None:
  74. above = lambda x: x >= offset + count
  75. else:
  76. above = lambda x: False
  77. for i, group in enumerate(x[0][1] for x in ldap_connect.ldap_search(
  78. base_dn, ldap.SCOPE_ONELEVEL, search_filter)):
  79. if below(i):
  80. continue
  81. if above(i):
  82. break
  83. yield UnixGroup(
  84. group['cn'][0],
  85. int(group['gidNumber'][0]),
  86. sorted(group.get('memberUid', [])),
  87. group['description'][0])
  88. def search_ldap_group(self, search_filter):
  89. for group in self.iterate_ldap_group(search_filter):
  90. return group
  91. return None
  92. def search_ldap_group_name(self, value):
  93. return self.search_ldap_group("cn=%s" % value)
  94. def gid_to_name(self, value):
  95. if value.isdigit():
  96. value = int(value)
  97. group = (self.search_ldap_group("gidNumber=%d" % value) or
  98. self.search_system_group_id(value))
  99. if group:
  100. return group.group_name
  101. return value
  102. def _groupname(self, name, comment):
  103. if comment != name:
  104. return "{0} ({1})".format(name, comment)
  105. else:
  106. return name
  107. def ldap_group_list(self):
  108. groups = list(x for x in self.iterate_ldap_group("cn=*"))
  109. return [(x.group_name, self._groupname(x.group_name, x.comment))
  110. for x in sorted(groups, key=lambda k: k.gid)]
  111. def ldap_group_names(self):
  112. return list(x.group_name for x in self.iterate_ldap_group("cn=*"))
  113. def check_group(self, value):
  114. ldap_group = self.search_ldap_group_name(value)
  115. unix_group = ldap_group or self.search_system_group_name(value)
  116. if not unix_group:
  117. raise self.exception(_("Group %s not found") % value)
  118. if not ldap_group and unix_group:
  119. raise self.exception(
  120. _("You should create group {groupname} ({groupid}) "
  121. "in Unix service").format(groupname=unix_group.group_name,
  122. groupid=unix_group.gid))
  123. def group_dn(self, group):
  124. return "cn=%s,%s" % (group, self.groups_dn)
  125. def add_users_to_group(self, users, group):
  126. try:
  127. self.ldap_connect.ldap_modify_attrs(
  128. self.group_dn(group),
  129. ((ldap.MOD_ADD, 'memberUid', user) for user in users))
  130. except LDAPConnectError as e:
  131. raise UnixError(_("Failed to modify group in LDAP: %s") % str(e))
  132. def update_group_id(self, group, gid):
  133. try:
  134. self.ldap_connect.ldap_modify_attrs(
  135. self.group_dn(group),
  136. [(ldap.MOD_REPLACE, 'gidNumber', gid)])
  137. except LDAPConnectError as e:
  138. raise UnixError(_("Failed to update group ID in LDAP: %s") % str(e))
  139. def update_group_comment(self, group, comment):
  140. try:
  141. self.ldap_connect.ldap_modify_attrs(
  142. self.group_dn(group),
  143. [(ldap.MOD_REPLACE, 'description', comment)])
  144. except LDAPConnectError as e:
  145. raise UnixError(
  146. _("Failed to update group comment in LDAP: %s") % str(e))
  147. def remove_users_from_group(self, users, group):
  148. try:
  149. self.ldap_connect.ldap_modify_attrs(
  150. self.group_dn(group),
  151. ((ldap.MOD_DELETE, 'memberUid', user) for user in users))
  152. except LDAPConnectError as e:
  153. raise UnixError(
  154. _("Failed to remove users from group in LDAP: %s") % str(e))
  155. def rename_group(self, oldname, newname):
  156. try:
  157. old_dn = self.group_dn(oldname)
  158. new_dn = "cn=%s" % newname
  159. self.ldap_connect.ldap_modify_dn(old_dn, new_dn)
  160. except LDAPConnectError as e:
  161. raise UnixError(
  162. _("Failed to rename group in LDAP: %s") % str(e))
  163. def remove_group(self, group):
  164. try:
  165. self.ldap_connect.ldap_remove_dn(self.group_dn(group))
  166. except LDAPConnectError as e:
  167. raise UnixError(
  168. _("Failed to remove the group in LDAP: %s") % str(e))
  169. UnixUser = namedtuple(
  170. "UnixUser", ['username', 'uid', 'gid', 'comment', 'homedir', 'shell',
  171. 'visible', 'lock', 'pass_set'])
  172. class PasswdFile(object):
  173. def __init__(self, passwd_fn='/etc/passwd'):
  174. self.passwd_fn = passwd_fn
  175. def __iter__(self):
  176. for line in (x for x in readLinesFile(self.passwd_fn)
  177. if not x.startswith("#")):
  178. data = line.strip().split(':')[:7]
  179. if len(data) >= 7 and data[2].isdigit() and data[3].isdigit():
  180. yield UnixUser(data[0], int(data[2]),
  181. int(data[3]), data[4], data[5], data[6], True,
  182. False, False)
  183. class UnixUsers(object):
  184. """
  185. Набор методов для нахождения параметров пользователя и сопаставления UID,
  186. названия
  187. """
  188. passwd = PasswdFile()
  189. exception = UnixError
  190. ldap_connect = None
  191. users_dn = ""
  192. DeletedPassword = "crypt{xxx}"
  193. def __init__(self, ldap_connect, users_dn):
  194. self.ldap_connect = ldap_connect
  195. self.users_dn = users_dn
  196. def search_system_user_name(self, name):
  197. for user in (x for x in self.passwd if x.username == name):
  198. return user
  199. else:
  200. return None
  201. def search_system_user_id(self, uid):
  202. uid = int(uid)
  203. for user in (x for x in self.passwd if x.uid == uid):
  204. return user
  205. else:
  206. return None
  207. def iterate_ldap_user(self, search_filter, offset=None, count=None):
  208. ldap_connect = self.ldap_connect
  209. if ldap_connect:
  210. base_dn = self.users_dn
  211. if offset is not None:
  212. below = lambda x: x < offset
  213. else:
  214. below = lambda x: False
  215. if count is not None:
  216. above = lambda x: x >= offset + count
  217. else:
  218. above = lambda x: False
  219. for i, user in enumerate(x[0][1] for x in ldap_connect.ldap_search(
  220. base_dn, ldap.SCOPE_ONELEVEL, search_filter)):
  221. if below(i):
  222. continue
  223. if above(i):
  224. break
  225. yield UnixUser(
  226. user['uid'][0],
  227. int(user['uidNumber'][0]),
  228. int(user['gidNumber'][0]),
  229. user['cn'][0],
  230. user['homeDirectory'][0],
  231. user['loginShell'][0],
  232. self.flag_to_visible(user['shadowFlag'][0]),
  233. self.flag_to_lock(user['shadowExpire'][0]),
  234. self.has_password(user['userPassword'][0])
  235. if 'userPassword' in user else None,
  236. )
  237. def search_ldap_user(self, search_filter):
  238. for user in self.iterate_ldap_user(search_filter):
  239. return user
  240. return None
  241. def has_password(self, password):
  242. if password and password != self.DeletedPassword:
  243. return True
  244. return False
  245. def search_ldap_user_name(self, value):
  246. return self.search_ldap_user("uid=%s" % value)
  247. def search_ldap_user_id(self, value):
  248. return self.search_ldap_user("uidNumber=%s" % value)
  249. def get_primary_gids(self):
  250. ldap_connect = self.ldap_connect
  251. if ldap_connect:
  252. base_dn = self.users_dn
  253. return list(ldap_connect.ldap_simple_search(
  254. base_dn, "uid=*", "gidNumber"))
  255. return []
  256. def get_password_hash(self, username):
  257. ldap_connect = self.ldap_connect
  258. if ldap_connect:
  259. base_dn = self.users_dn
  260. for pw in ldap_connect.ldap_simple_search(
  261. self.users_dn, "uid=%s" % username, "userPassword"):
  262. return pw
  263. return ""
  264. def uid_to_name(self, value):
  265. if value.isdigit():
  266. value = int(value)
  267. user = (self.search_ldap_user("uidNumber=%d" % value) or
  268. self.search_system_user_id(value))
  269. if user:
  270. return user.username
  271. return value
  272. def _username(self, name, comment):
  273. if comment != name:
  274. return "{0} ({1})".format(name, comment)
  275. else:
  276. return name
  277. def ldap_user_list(self):
  278. users = list(x for x in self.iterate_ldap_user("uid=*"))
  279. return [(x.username, self._username(x.username, x.comment))
  280. for x in sorted(users, key=lambda y: y.uid)]
  281. def ldap_user_names(self):
  282. return list(x.username for x in self.iterate_ldap_user("uid=*"))
  283. # def check_user(self, value):
  284. # ldap_user = self.search_ldap_user_name(value)
  285. # unix_user = ldap_user or self.search_system_user_name(value)
  286. # if not unix_user:
  287. # raise VariableError(_("User %s not found") % value)
  288. # if not ldap_user and unix_user:
  289. # raise VariableError(
  290. # _("You should create group %s (%d) in Unix service") %
  291. # (unix_group.group_name, unix_group.gid))
  292. def user_dn(self, user):
  293. return "uid=%s,%s" % (user, self.users_dn)
  294. def update_user_group_id(self, user, gid):
  295. try:
  296. self.ldap_connect.ldap_modify_attrs(
  297. self.user_dn(user),
  298. [(ldap.MOD_REPLACE, 'gidNumber', gid)])
  299. except LDAPConnectError as e:
  300. raise UnixError(
  301. _("Failed to modify user primary group in LDAP: %s") % str(e))
  302. def visible_to_flag(self, visible):
  303. return "1" if visible else "0"
  304. def flag_to_visible(self, flag):
  305. return flag == "1"
  306. def lock_to_flag(self, lock):
  307. return "1" if lock else "-1"
  308. def flag_to_lock(self, flag):
  309. return flag == "1"
  310. def modify_user(self, username, pw=None, gid=None, shell=None, visible=None,
  311. lock=None, comment=None, homedir=None):
  312. attributes = []
  313. if pw is not None:
  314. attributes.append((ldap.MOD_REPLACE, 'userPassword', str(pw)))
  315. if gid is not None:
  316. attributes.append((ldap.MOD_REPLACE, 'gidNumber', str(gid)))
  317. if shell is not None:
  318. attributes.append((ldap.MOD_REPLACE, 'loginShell', shell))
  319. if comment is not None:
  320. attributes.append((ldap.MOD_REPLACE, 'cn', comment))
  321. if homedir is not None:
  322. attributes.append((ldap.MOD_REPLACE, 'homeDirectory', homedir))
  323. if visible is not None:
  324. attributes.append(
  325. (ldap.MOD_REPLACE, 'shadowFlag',
  326. self.visible_to_flag(visible)))
  327. if lock is not None:
  328. attributes.append(
  329. (ldap.MOD_REPLACE, 'shadowExpire', self.lock_to_flag(lock)))
  330. try:
  331. self.ldap_connect.ldap_modify_attrs(
  332. self.user_dn(username), attributes)
  333. except LDAPConnectError as e:
  334. raise UnixError(
  335. _("Failed to modify user parameters in LDAP: %s") % str(e))
  336. def remove_user(self, username):
  337. try:
  338. self.ldap_connect.ldap_remove_dn(self.user_dn(username))
  339. except LDAPConnectError as e:
  340. raise UnixError(_("Failed to remove user from LDAP: %s") % str(e))
  341. class Unix(Ldap):
  342. """Основной объект для выполнения действий связанных
  343. с настройкой Unix сервиса
  344. """
  345. class Method(object):
  346. Setup = "unix_setup"
  347. UserAdd = "unix_useradd"
  348. UserMod = "unix_usermod"
  349. UserDel = "unix_userdel"
  350. UserShow = "unix_usershow"
  351. GroupAdd = "unix_groupadd"
  352. GroupMod = "unix_groupmod"
  353. GroupDel = "unix_groupdel"
  354. GroupShow = "unix_groupshow"
  355. Passwd = "unix_passwd"
  356. All = (
  357. Setup, UserAdd, UserMod, UserDel, GroupAdd, GroupMod, GroupDel,
  358. Passwd,
  359. UserShow, GroupShow)
  360. service_name = "unix"
  361. def init(self):
  362. pass
  363. def rename_group(self, oldname, newname):
  364. """
  365. Переименовать группу
  366. """
  367. if oldname != newname and newname:
  368. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  369. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  370. ug = UnixGroups(ldap_connect, groups_dn)
  371. ug.rename_group(oldname, newname)
  372. return True
  373. def update_group_comment(self, group, comment):
  374. """
  375. Переименовать группу
  376. """
  377. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  378. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  379. ug = UnixGroups(ldap_connect, groups_dn)
  380. ug.update_group_comment(group, comment)
  381. return True
  382. def update_group_id(self, group, gid, old_gid):
  383. """
  384. Обновить gid группы
  385. """
  386. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  387. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  388. ug = UnixGroups(ldap_connect, groups_dn)
  389. ug.update_group_id(group, str(gid))
  390. users_dn = self.clVars.Get('ld_unix_users_dn')
  391. uu = UnixUsers(ldap_connect, users_dn)
  392. for user in uu.iterate_ldap_user("gidNumber=%d" % old_gid):
  393. self.printSUCCESS(_("Changed primary group for user {user}").format(
  394. user=user.username))
  395. uu.update_user_group_id(user.username, str(gid))
  396. return True
  397. def remove_group(self, groupname):
  398. """
  399. Удалить группу
  400. """
  401. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  402. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  403. ug = UnixGroups(ldap_connect, groups_dn)
  404. ug.remove_group(groupname)
  405. return True
  406. def remove_user(self, username):
  407. """
  408. Удалить пользователя
  409. """
  410. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  411. users_dn = self.clVars.Get('ld_unix_users_dn')
  412. uu = UnixUsers(ldap_connect, users_dn)
  413. uu.remove_user(username)
  414. return True
  415. def _add_users_in_group(self, users, groupname):
  416. """
  417. Добавить пользователей в группу
  418. """
  419. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  420. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  421. ug = UnixGroups(ldap_connect, groups_dn)
  422. group = ug.search_ldap_group_name(groupname)
  423. if group:
  424. exists_users = group.user_list
  425. new_users = set(users) - set(exists_users)
  426. ug.add_users_to_group(new_users, groupname)
  427. return True
  428. return False
  429. def remove_users_from_group(self, users, groupname):
  430. self._remove_users_from_group(users, groupname)
  431. self.printSUCCESS(_("Users {logins} were removed from "
  432. "group {group}").format(
  433. logins=", ".join(users), group=groupname))
  434. return True
  435. def add_users_in_group(self, users, groupname):
  436. self._add_users_in_group(users, groupname)
  437. self.printSUCCESS(_("Users {logins} were added "
  438. "to group {group}").format(
  439. logins=", ".join(users), group=groupname))
  440. return True
  441. def _remove_users_from_group(self, users, groupname):
  442. """
  443. Удалить пользователей из групп
  444. """
  445. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  446. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  447. ug = UnixGroups(ldap_connect, groups_dn)
  448. group = ug.search_ldap_group_name(groupname)
  449. if group:
  450. exists_users = group.user_list
  451. remove_users = set(exists_users) & set(users)
  452. ug.remove_users_from_group(list(remove_users), groupname)
  453. return True
  454. return False
  455. def add_user_in_groups(self, user, groups):
  456. """
  457. Добавить пользователя в группы
  458. """
  459. for group in groups:
  460. self._add_users_in_group([user], group)
  461. self.printSUCCESS(_("User {login} was added "
  462. "to groups {groups}").format(
  463. login=user, groups=", ".join(groups)))
  464. return True
  465. def remove_user_from_groups(self, user, groups):
  466. """
  467. Удалить пользователя из группы
  468. """
  469. for group in groups:
  470. self._remove_users_from_group([user], group)
  471. self.printSUCCESS(_("User {login} was removed "
  472. "from groups {groups}").format(
  473. login=user, groups=", ".join(groups)))
  474. return True
  475. def modify_user(self, login, pw, pw_delete, gid, shell, visible, lock,
  476. comment, homedir):
  477. """"
  478. Изменить параметры пользователя в LDAP
  479. """
  480. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  481. users_dn = self.clVars.Get('ld_unix_users_dn')
  482. uu = UnixUsers(ldap_connect, users_dn)
  483. user = uu.search_ldap_user_name(login)
  484. if user:
  485. params = {}
  486. if gid is not None and user.gid != gid:
  487. params['gid'] = str(gid)
  488. self.printSUCCESS(
  489. _("Changed primary group for user {user}").format(
  490. user.username))
  491. if comment is not None and user.comment != comment:
  492. params['comment'] = comment
  493. self.printSUCCESS(
  494. _("Changed comment for user %s") % user.username)
  495. if homedir is not None and user.homedir != homedir:
  496. params['homedir'] = homedir
  497. self.printSUCCESS(
  498. _("Changed home directory for user %s") % user.username)
  499. if pw != UnixUsers.DeletedPassword or pw_delete:
  500. params['pw'] = pw
  501. if pw_delete:
  502. self.printSUCCESS(
  503. _("Removed password for user %s") % user.username)
  504. else:
  505. self.printSUCCESS(
  506. _("Changed password for user %s") % user.username)
  507. if shell and user.shell != shell:
  508. params['shell'] = shell
  509. self.printSUCCESS(
  510. _("Changed shell for user %s") % user.username)
  511. if visible is not None:
  512. if user.visible != visible:
  513. params['visible'] = visible
  514. if visible:
  515. self.printSUCCESS(
  516. _("User %s is visible") % user.username)
  517. else:
  518. self.printSUCCESS(
  519. _("User %s is unvisible") % user.username)
  520. else:
  521. if visible:
  522. self.printWARNING(
  523. _("User %s is visible already") % user.username)
  524. else:
  525. self.printWARNING(
  526. _("User %s is already unvisible") % user.username)
  527. if lock is not None:
  528. if user.lock != lock:
  529. params['lock'] = lock
  530. if lock:
  531. self.printSUCCESS(
  532. _("User %s is locked") % user.username)
  533. else:
  534. self.printSUCCESS(
  535. _("User %s is unlocked") % user.username)
  536. else:
  537. if lock:
  538. self.printWARNING(
  539. _("User %s is locked already") % user.username)
  540. else:
  541. self.printWARNING(
  542. _("User %s is unlocked already") % user.username)
  543. uu.modify_user(user.username, **params)
  544. else:
  545. raise UnixError(_("User %s not found") % user)
  546. return True
  547. def move_home_directory(self, homedir, new_homedir):
  548. """
  549. Преместить домашнюю директорию пользователя
  550. """
  551. if not path.exists(homedir):
  552. self.printWARNING(_("Previous home directory %s not found")
  553. % homedir)
  554. return True
  555. try:
  556. self.printSUCCESS(
  557. _("User home directory {homedir} "
  558. "moved to {new_homedir}").format(
  559. homedir=homedir, new_homedir=new_homedir))
  560. dirname = path.dirname(new_homedir)
  561. if not path.exists(dirname):
  562. os.makedirs(dirname)
  563. os.rename(homedir, new_homedir)
  564. except (OSError, IOError):
  565. raise UnixError(_("Failed to move home directory"))
  566. return True
  567. def create_home_directory(self, homedir, uid, gid, skel):
  568. """
  569. Создать домашнюю директорию пользователя
  570. """
  571. try:
  572. os.makedirs(homedir, 0700)
  573. if path.exists(skel):
  574. for fn in listDirectory(skel):
  575. src_fn = path.join(skel, fn)
  576. dst_fn = path.join(homedir, fn)
  577. if path.isdir(src_fn):
  578. shutil.copytree(src_fn, dst_fn, True)
  579. elif path.islink(src_fn):
  580. link_src = os.readlink(src_fn)
  581. os.symlink(link_src, dst_fn)
  582. else:
  583. shutil.copy2(src_fn, dst_fn)
  584. for root, dns, fns in os.walk(homedir):
  585. for fn in (path.join(root, x) for x in dns + fns):
  586. os.lchown(fn, uid, gid)
  587. os.lchown(homedir, uid, gid)
  588. except (OSError, IOError) as e:
  589. self.printWARNING(str(e))
  590. raise UnixError(_("Failed to create user home directory"))
  591. return True
  592. def show_groups(self, groupname, fields, count, offset):
  593. dv = self.clVars
  594. fields = ["ur_unix_group_name"] + list(fields)
  595. head = [dv.getInfo(x).label for x in fields]
  596. body = []
  597. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  598. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  599. ug = UnixGroups(ldap_connect, groups_dn)
  600. users_dn = self.clVars.Get('ld_unix_users_dn')
  601. uu = UnixUsers(ldap_connect, users_dn)
  602. filters = (self.clVars.getInfo(x)
  603. for x in ('cl_unix_group_filter_name',
  604. 'cl_unix_group_filter_id',
  605. 'cl_unix_group_filter_comment',
  606. 'cl_unix_group_filter_users'))
  607. filters = [x.test for x in filters if x.enabled()]
  608. def all_users(group):
  609. for user in sorted(uu.iterate_ldap_user("gidNumber=%d" % group.gid),
  610. key=lambda x: x.username):
  611. yield "<%s>" % user.username
  612. for user in group.user_list:
  613. yield user
  614. variables_mapping = {
  615. 'ur_unix_group_name': lambda group: group.group_name,
  616. 'ur_unix_group_id': lambda group: str(group.gid),
  617. 'ur_unix_group_comment': lambda group: group.comment,
  618. 'ur_unix_group_users': lambda group: ", ".join(all_users(group))
  619. }
  620. mapping = {'ur_unix_group_name': 'ur_unix_group_name_exists'}
  621. maxi = 0
  622. try:
  623. for i, group in enumerate(sorted(
  624. (group for group in
  625. ug.iterate_ldap_group("cn=*")
  626. if all(x(group) for x in filters)),
  627. key=lambda x: x.group_name)):
  628. maxi = i
  629. if offset <= i < offset + count:
  630. body.append(
  631. [variables_mapping.get(x)(group) for x in fields])
  632. except LDAPBadSearchFilter:
  633. raise UnixError(_("Wrong group pattern"))
  634. table_fields = [mapping.get(x, '') for x in fields]
  635. if not body:
  636. body = [[]]
  637. dv.Invalidate('ur_unix_group_count')
  638. if any(body):
  639. head_message = _("Groups")
  640. elif dv.GetInteger("ur_unix_group_count"):
  641. head_message = _("Groups not found")
  642. else:
  643. head_message = _("No groups")
  644. self.printTable(
  645. head_message, head, body,
  646. fields=table_fields,
  647. onClick='unix_groupmod' if any(table_fields) else None,
  648. addAction='unix_groupadd',
  649. records=str(maxi + 1))
  650. if any(body):
  651. num_page, count_page = getPagesInterval(
  652. count, offset, maxi + 1)
  653. self.printSUCCESS(_('page %d of ') % num_page + str(count_page))
  654. return True
  655. def show_group(self, groupname):
  656. dv = self.clVars
  657. list_group_name = sorted(dv.Choice('cl_core_group'))
  658. if not list_group_name:
  659. self.printSUCCESS(_("No groups"))
  660. head = [_('Field'), _('Value')]
  661. body = []
  662. fields = [
  663. 'ur_unix_group_name',
  664. 'ur_unix_group_id',
  665. 'ur_unix_group_comment',
  666. 'ur_unix_group_users'
  667. ]
  668. def get_primary_users(gid):
  669. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  670. users_dn = self.clVars.Get('ld_unix_users_dn')
  671. uu = UnixUsers(ldap_connect, users_dn)
  672. for user in sorted(uu.iterate_ldap_user("gidNumber=%d" % gid),
  673. key=lambda x: x.username):
  674. yield "<%s>" % user.username
  675. self.clVars.Set('ur_unix_group_name', groupname, True)
  676. gid = self.clVars.GetInteger('ur_unix_group_id')
  677. for varname in fields:
  678. varval = self.clVars.Get(varname)
  679. varobj = self.clVars.getInfo(varname)
  680. if varname == 'ur_unix_group_users':
  681. varval = (sorted(get_primary_users(gid))
  682. + sorted(varval))
  683. if "list" in varobj.type:
  684. varval = "\n".join(varval)
  685. body.append([varobj.label or "", varval])
  686. if body:
  687. self.printTable(_("Group info"), head, body,
  688. onClick="unix_groupmod",
  689. records="0",
  690. fields=["ur_unix_group_name_exists:%s" % groupname])
  691. return True
  692. def show_users(self, login, fields, count, offset):
  693. dv = self.clVars
  694. fields = ["ur_unix_login"] + list(fields)
  695. head = [dv.getInfo(x).label for x in fields]
  696. body = []
  697. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  698. users_dn = self.clVars.Get('ld_unix_users_dn')
  699. uu = UnixUsers(ldap_connect, users_dn)
  700. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  701. ug = UnixGroups(ldap_connect, groups_dn)
  702. yesno_map = {True: _("Yes"),
  703. False: _("No"),
  704. None: _("Unavailable")}
  705. yesno = lambda x: yesno_map.get(x, _("Failed value"))
  706. filters = (self.clVars.getInfo(x)
  707. for x in ('cl_unix_user_filter_login',
  708. 'cl_unix_user_filter_pw_set',
  709. 'cl_unix_user_filter_comment',
  710. 'cl_unix_user_filter_uid',
  711. 'cl_unix_user_filter_gid',
  712. 'cl_unix_user_filter_home_path',
  713. 'cl_unix_user_filter_shell',
  714. 'cl_unix_user_filter_groups',
  715. 'cl_unix_user_filter_visible_set',
  716. 'cl_unix_user_filter_lock_set',
  717. ))
  718. filters = [x.test for x in filters if x.enabled()]
  719. variables_mapping = {
  720. 'ur_unix_uid': lambda user: user.uid,
  721. 'ur_unix_login': lambda user: user.username,
  722. 'ur_unix_comment': lambda user: user.comment,
  723. 'ur_unix_lock_set': lambda user: yesno(user.lock),
  724. 'ur_unix_visible_set': lambda user: yesno(user.visible),
  725. 'ur_unix_primary_group': lambda user: ug.gid_to_name(str(user.gid)),
  726. 'ur_unix_groups': lambda user: ", ".join(
  727. x.group_name for x in ug.iterate_ldap_group(
  728. "memberUid=%s" % user.username)
  729. ),
  730. 'ur_unix_home_path': lambda user: user.homedir,
  731. 'ur_unix_shell': lambda user: user.shell,
  732. 'ur_unix_pw_set': lambda user: yesno(user.pass_set),
  733. }
  734. mapping = {'ur_unix_login': 'ur_unix_login_exists'}
  735. maxi = 0
  736. try:
  737. for i, user in enumerate(sorted(
  738. (user for user in uu.iterate_ldap_user("uid=*")
  739. if all(x(user) for x in filters)),
  740. key=lambda x: x.username)):
  741. maxi = i
  742. if offset <= i < offset + count:
  743. body.append(
  744. [variables_mapping.get(x)(user) for x in fields])
  745. except LDAPBadSearchFilter:
  746. raise UnixError(_("Wrong user pattern"))
  747. table_fields = [mapping.get(x, '') for x in fields]
  748. if not body:
  749. body = [[]]
  750. dv.Invalidate('ur_unix_user_count')
  751. if any(body):
  752. head_message = _("Users")
  753. elif dv.GetInteger("ur_unix_user_count"):
  754. head_message = _("Users not found")
  755. else:
  756. head_message = _("No users")
  757. self.printTable(head_message,
  758. head, body,
  759. fields=table_fields,
  760. onClick='unix_usermod' if any(table_fields) else None,
  761. addAction='unix_useradd',
  762. records=str(maxi + 1))
  763. if any(body):
  764. num_page, count_page = getPagesInterval(
  765. count, offset, maxi + 1)
  766. self.printSUCCESS(_('page %d of ') % num_page + str(count_page))
  767. return True
  768. def show_user(self, user):
  769. dv = self.clVars
  770. head = [_('Field'), _('Value')]
  771. body = []
  772. fields = [
  773. 'ur_unix_uid',
  774. 'ur_unix_login',
  775. 'ur_unix_comment',
  776. 'ur_unix_lock_set',
  777. 'ur_unix_visible_set',
  778. 'ur_unix_primary_group',
  779. 'ur_unix_groups',
  780. 'ur_unix_home_path',
  781. 'ur_unix_shell',
  782. 'ur_unix_pw_set',
  783. ]
  784. self.clVars.Set('ur_unix_login', user, True)
  785. for varname in fields:
  786. varval = self.clVars.Get(varname)
  787. varobj = self.clVars.getInfo(varname)
  788. if "list" in varobj.type:
  789. varval = "\n".join(varval)
  790. body.append([varobj.label or "", varval])
  791. if body:
  792. self.printTable(_("User info"), head, body,
  793. onClick="unix_usermod",
  794. records="0",
  795. fields=["ur_unix_login_exists:%s" % user])
  796. return True
  797. def try_remove_primary_group(self, user, primary_group):
  798. """
  799. Primary group
  800. :param primary_group:
  801. :return:
  802. """
  803. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  804. groups_dn = self.clVars.Get('ld_unix_groups_dn')
  805. ug = UnixGroups(ldap_connect, groups_dn)
  806. filter_str = "gidNumber={0}".format(primary_group)
  807. filter_str2 = "(&(gidNumber={0})(!(uid={1})))".format(
  808. primary_group, user)
  809. group = ug.search_ldap_group(filter_str)
  810. ldap_connect = self.clVars.Get('ldap.cl_ldap_connect')
  811. users_dn = self.clVars.Get('ld_unix_users_dn')
  812. uu = UnixUsers(ldap_connect, users_dn)
  813. if group:
  814. if not group.user_list and not uu.search_ldap_user(filter_str2):
  815. self.remove_group(group.group_name)
  816. self.printSUCCESS(_("Removed user primary group {0}").format(
  817. group.group_name))
  818. return True