Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

738 рядки
21 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. import sys
  16. from os import path
  17. from calculate.lib.cl_ldap import LDAPConnectError
  18. from calculate.lib.datavars import (ReadonlyVariable, Variable,
  19. VariableError, PasswordError,
  20. VariableInterface)
  21. from calculate.ldap.variables.helpers import (HashHelper,
  22. LdapMaxHelper)
  23. from calculate.unix.variables.helpers import (UnixUserHelper, UnixGroupHelper,
  24. ExistsUserHelper,
  25. ShowFieldsHelper,
  26. FieldsHelper, UnixActionHelper)
  27. from .action import Actions
  28. import re
  29. _ = lambda x: x
  30. from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
  31. setLocalTranslate('cl_unix3', sys.modules[__name__])
  32. __ = getLazyLocalTranslate(_)
  33. class UserNameHelper(VariableInterface):
  34. """
  35. Вспомогательный объект для проверки имени группы
  36. """
  37. def check_user_name(self, uname):
  38. if len(uname) > 32:
  39. raise VariableError(_("Wrong user name length"))
  40. if ":" in uname:
  41. raise VariableError(_("Wrong user name"))
  42. class VariableUrUnixLogin(UserNameHelper, UnixUserHelper, UnixActionHelper,
  43. Variable):
  44. """
  45. Логин настраиваемого пользователя
  46. """
  47. untrusted = True
  48. opt = ("ur_unix_login",)
  49. metavalue = "USER"
  50. def init(self):
  51. self.label = _("Login")
  52. self.help = _("set user login")
  53. def get_new(self):
  54. return ""
  55. def get_exists(self):
  56. return self.Get('ur_unix_login_exists')
  57. def check_new(self, value):
  58. if not value:
  59. raise VariableError(_("Please specify the login"))
  60. self.check_user_name(value)
  61. if value == "list":
  62. raise VariableError(_("List is used as keyword"))
  63. if self.search_ldap_user_name(value):
  64. raise VariableError(_("User %s already exists" % value))
  65. if self.search_system_user_name(value):
  66. raise VariableError(
  67. _("User %s is already in /etc/passwd") % value)
  68. class VariableUrUnixLoginExists(UnixUserHelper, UnixActionHelper, Variable):
  69. """
  70. Логин настраиваемого пользователя
  71. """
  72. type = "choice"
  73. opt = ("ur_unix_login_exists",)
  74. metavalue = "USER"
  75. untrusted = True
  76. guitype = "readonly"
  77. def init(self):
  78. self.label = _("Login")
  79. self.help = _("set user login")
  80. def get_new(self):
  81. return ""
  82. def get_exists(self):
  83. return ""
  84. def choice_exists(self):
  85. return ((user.username,
  86. "%s (%s)" % (user.username, user.comment))
  87. for user in self.iterate_ldap_user("uid=*"))
  88. def raiseWrongChoice(self, name, choiceVal, value, error):
  89. if not value:
  90. raise VariableError(_("Please specify the user login"))
  91. else:
  92. raise VariableError(_("%s user not found") % value)
  93. class VariableUrUnixBaseDir(Variable):
  94. """
  95. Базовая директория для нового пользователя
  96. """
  97. value = "/home"
  98. opt = ('-b', '--base-dir')
  99. metavalue = "BASE_DIR"
  100. def init(self):
  101. self.label = _("Base directory")
  102. self.help = _("base directory for new account's home")
  103. class VariableUrUnixComment(ExistsUserHelper, UnixActionHelper, Variable):
  104. """
  105. Описание учётной записи
  106. """
  107. attribute = "comment"
  108. value_format = "{ldap.ld_base_root.capitalize()} user"
  109. opt = ('-c', '--comment')
  110. metavalue = "COMMENT"
  111. def init(self):
  112. self.label = _("Full name")
  113. self.help = _("set full name for account")
  114. def get_new(self):
  115. return ""
  116. # self._value_formatter.format(self.value_format, self.Get)
  117. class VariableUrUnixHomePath(ExistsUserHelper, UnixActionHelper, Variable):
  118. """
  119. Путь до домашней директории
  120. """
  121. value_format = "{unix.ur_unix_base_dir}/{unix.ur_unix_login}"
  122. opt = ('-d', '--home-dir')
  123. metavalue = "HOME_DIR"
  124. check_after = ["ur_unix_login"]
  125. def init(self):
  126. self.label = _("Home directory")
  127. self.help = _("set home directory for account")
  128. def get_exists(self):
  129. return self.Get('ur_unix_home_path_exists')
  130. def get_new(self):
  131. return self._value_formatter.format(self.value_format, self.Get)
  132. def check_exists(self, value):
  133. if "," in value:
  134. raise VariableError(_("Non-existing home directory"))
  135. if not value.startswith('/'):
  136. raise VariableError(_("Home must have an absolute path"))
  137. class VariableUrUnixHomePathExists(ExistsUserHelper, UnixActionHelper,
  138. ReadonlyVariable):
  139. """
  140. Путь до домашней директории
  141. """
  142. attribute = "homedir"
  143. class VariableUrUnixHomePathMove(Variable):
  144. """
  145. Перемещать домашнуюю пользовательскую директорию
  146. """
  147. type = "bool"
  148. opt = ('-m', '--move-home')
  149. value = "off"
  150. check_after = ["ur_unix_home_path", "ur_unix_home_path_exists"]
  151. def init(self):
  152. self.label = _("Move home directory")
  153. self.help = _("move home conents to new location")
  154. def check_on(self):
  155. new_path = self.Get('ur_unix_home_path')
  156. old_path = self.Get('ur_unix_home_path_exists')
  157. if new_path == old_path:
  158. raise VariableError(_("Please change home directory"))
  159. if path.exists(new_path):
  160. raise VariableError(
  161. _("New home directory %s already exists") % new_path)
  162. class VariableClUnixGroupDefault(Variable):
  163. """
  164. Основная группа пользователя по умолчанию
  165. """
  166. value = "domain"
  167. class VariableUrUnixPrimaryGroup(ExistsUserHelper, UnixGroupHelper,
  168. UnixActionHelper, Variable):
  169. """
  170. ID основной группы
  171. """
  172. attribute = "gid"
  173. type = "choiceedit"
  174. opt = ('-g', '--gid')
  175. metavalue = "GROUP"
  176. @property
  177. def domain_group(self):
  178. return self.Get('cl_unix_group_default')
  179. def init(self):
  180. self.label = _("Primary group")
  181. self.help = _("set name or ID of primary group for account "
  182. "('default' creates a default group)")
  183. def get_new(self):
  184. return self.domain_group
  185. def get_exists(self):
  186. value = str(ExistsUserHelper.get_exists(self))
  187. if value:
  188. return str(self.gid_to_name(value))
  189. def set(self, value):
  190. return str(self.gid_to_name(value))
  191. def choice_new(self):
  192. return ([(self.domain_group, self.domain_group)]
  193. + self.ldap_group_list())
  194. def choice_exists(self):
  195. return self.ldap_group_list()
  196. def check_new(self, value):
  197. if not value:
  198. raise VariableError(_("Please specify the primary group ID"))
  199. def check_exists(self, value):
  200. if not value:
  201. raise VariableError(_("Please specify the primary group ID"))
  202. if value:
  203. self.check_group(value)
  204. def raiseWrongChoice(self, name, choiceVal, value, error):
  205. raise VariableError(_("Group %s not found") % value)
  206. class VariableUrUnixGid(UnixGroupHelper, ReadonlyVariable):
  207. """
  208. ID основной группы пользователя
  209. """
  210. type = "int"
  211. def get(self):
  212. group_name = self.Get('ur_unix_primary_group')
  213. group = self.search_ldap_group_name(group_name)
  214. if group:
  215. return str(group.gid)
  216. else:
  217. return self.Get('ur_unix_next_gid')
  218. class VariableUrUnixUid(UnixUserHelper, UnixActionHelper, Variable):
  219. """
  220. UID пользователя
  221. """
  222. type = "int"
  223. opt = ('-u', '--uid')
  224. metavalue = "UID"
  225. value = ""
  226. def init(self):
  227. self.label = _("User ID")
  228. self.help = _("set user ID")
  229. def get_new(self):
  230. return self.Get('ur_unix_next_uid')
  231. def get_exists(self):
  232. login = self.Get('ur_unix_login')
  233. if login:
  234. return str(self.search_ldap_user_name(login).uid)
  235. def check_new(self, value):
  236. user = self.search_ldap_user_id(value)
  237. if user:
  238. raise VariableError(
  239. _("UID {userid} is used by user {username}").format(
  240. userid=user.uid, username=user.username))
  241. user = self.search_system_user_id(value)
  242. if user:
  243. raise VariableError(
  244. _("UID {userid} is used by system user {username}").format(
  245. userid=user.uid, username=user.username))
  246. class VariableUrUnixGroups(UnixGroupHelper, UnixActionHelper, Variable):
  247. """
  248. Список груп
  249. """
  250. type = "choiceedit-list"
  251. opt = ("-G", "--groups")
  252. metavalue = "GROUPS"
  253. value = []
  254. def init(self):
  255. self.label = _("Supplementary groups")
  256. self.help = _("set list of supplementary groups for account")
  257. def set(self, value):
  258. return map(self.gid_to_name, value)
  259. def get_exists(self):
  260. return self.Get('ur_unix_groups_exists')
  261. def choice(self):
  262. return self.ldap_group_list()
  263. def check(self, value):
  264. for group in value:
  265. self.check_group(group)
  266. class VariableUrUnixGroupsExists(UnixGroupHelper, UnixActionHelper, Variable):
  267. """
  268. Список груп
  269. """
  270. type = "list"
  271. value = []
  272. # def get_bylogin(self, login, obj):
  273. # return [x.group_name for x in
  274. # self.iterate_ldap_group("memberUid=%s" % login)]
  275. def get_exists(self):
  276. login = self.Get('ur_unix_login')
  277. if login:
  278. return [x.group_name for x in
  279. self.iterate_ldap_group("memberUid=%s" % login)]
  280. return []
  281. class VariableUrUnixGroupsAdd(UnixGroupHelper, UnixActionHelper, Variable):
  282. """
  283. Список групп в которые необходимо добавить пользователя
  284. """
  285. type = "choiceedit-list"
  286. guitype = "hidden"
  287. opt = ("-a", "--append")
  288. metavalue = "GROUPS"
  289. value = []
  290. def init(self):
  291. self.label = _("Include to groups")
  292. self.help = _("include user into groups")
  293. def set(self, value):
  294. return map(self.gid_to_name, value)
  295. def get_exists(self):
  296. exists_groups = set(self.Get('ur_unix_groups_exists'))
  297. replace_group = set(self.Get('ur_unix_groups'))
  298. return sorted(list(replace_group - exists_groups))
  299. def choice_exists(self):
  300. login = self.Get('ur_unix_login')
  301. if login:
  302. exists_groups = self.Get('ur_unix_groups_exists')
  303. return (x for x in self.ldap_group_list()
  304. if x[0] not in exists_groups)
  305. return []
  306. def check_exists(self, value):
  307. exists_groups = self.Get('ur_unix_groups_exists')
  308. replace_groups = self.Get('ur_unix_groups')
  309. if set(exists_groups) != set(replace_groups):
  310. raise VariableError(_(
  311. "You cannot add user to group and replace their groups"))
  312. login = self.Get('ur_unix_login')
  313. groups = self.ldap_group_names()
  314. failed = [x for x in value if x not in groups]
  315. if failed:
  316. raise VariableError(
  317. _("Wrong groups {groups}").format(
  318. groups=", ".join(failed)))
  319. self.check_special(value, exists_groups, login)
  320. def check_special(self, value, exists_groups, login):
  321. already_exists = [x for x in value if x in exists_groups]
  322. if already_exists:
  323. raise VariableError(
  324. _("User {user} already exist in groups {groups}").format(
  325. groups=", ".join(already_exists), user=login))
  326. def humanReadable(self):
  327. if not self.Get():
  328. return _("Do not change")
  329. class VariableUrUnixGroupsDel(VariableUrUnixGroupsAdd):
  330. """
  331. Список групп из которых необходимо исключить пользователя
  332. """
  333. type = "choiceedit-list"
  334. opt = ("-r", "--remove")
  335. guitype = "hidden"
  336. metavalue = "GROUPS"
  337. value = []
  338. def init(self):
  339. self.label = _("Exclude from groups")
  340. self.help = _("exclude user from groups")
  341. def get_exists(self):
  342. exists_groups = set(self.Get('ur_unix_groups_exists'))
  343. replace_groups = set(self.Get('ur_unix_groups'))
  344. return sorted(list(exists_groups - replace_groups))
  345. def choice_exists(self):
  346. login = self.Get('ur_unix_login')
  347. if login:
  348. exists_groups = self.Get('ur_unix_groups_exists')
  349. return (x for x in self.ldap_group_list()
  350. if x[0] in exists_groups)
  351. return []
  352. def check_special(self, value, exists_groups, login):
  353. not_exists = [x for x in value if x not in exists_groups]
  354. if not_exists:
  355. raise VariableError(
  356. _("No user {user} was found in groups {groups}").format(
  357. groups=", ".join(not_exists), user=login))
  358. class VariableUrUnixSkel(Variable):
  359. """
  360. Skel директория
  361. """
  362. opt = ("-k", "--skel")
  363. metavalue = "SKEL_DIR"
  364. value = "/etc/skel"
  365. def init(self):
  366. self.label = _("Skeleton directory")
  367. self.help = _("use alternative skeleton directory")
  368. class VariableUrUnixCreateHomeSet(Variable):
  369. """
  370. Создавать домашнюю директорию пользователю
  371. """
  372. type = "bool"
  373. opt = ("-m", "--create-home")
  374. value = "off"
  375. check_after = ["ur_unix_home_path"]
  376. def init(self):
  377. self.label = _("Create home directory")
  378. self.help = _("create user's home directory")
  379. def check_on(self):
  380. home_path = self.Get('ur_unix_home_path')
  381. if path.exists(home_path):
  382. raise VariableError(
  383. _("Home directory %s already exists") % home_path)
  384. class VariableUrUnixPw(Variable):
  385. """
  386. Пароль пользователя
  387. """
  388. type = "password"
  389. opt = ("-p", "--password")
  390. value = ""
  391. untrusted = True
  392. metavalue = "PASSWORD"
  393. check_after = ["ur_unix_pw_delete_set", 'ur_unix_lock_set']
  394. def init(self):
  395. self.label = _("Password")
  396. self.help = _("set user password")
  397. def check(self, value):
  398. delete_pw = self.GetBool('ur_unix_pw_delete_set')
  399. change_lock = self.GetBool('ur_unix_lock_set')
  400. if (self.Get('cl_unix_action') == Actions.Passwd and
  401. not delete_pw and change_lock is None and not value):
  402. raise PasswordError(_("Specify user password"))
  403. if self.Get('cl_unix_action') in (Actions.Passwd, Actions.UserMod):
  404. if self.Get('ur_unix_pw_delete_set') == 'on' and value:
  405. raise VariableError(_("You cannot use remove and password "
  406. "setup options together"))
  407. class VariableUrUnixPwSet(UnixActionHelper, UnixUserHelper, ReadonlyVariable):
  408. """
  409. Указан ли пароль у пользователя
  410. """
  411. type = "bool"
  412. def init(self):
  413. self.label = _("Password")
  414. def get_exists(self):
  415. username = self.Get('ur_unix_login')
  416. pw = self.get_password_hash(username)
  417. if pw and pw != self.DeletedPassword:
  418. return "on"
  419. else:
  420. return "off"
  421. class VariableUrUnixPwDeleteSet(Variable):
  422. """
  423. Удалить пароль пользователя
  424. """
  425. type = "bool"
  426. value = "off"
  427. opt = ("--delete-password",)
  428. def init(self):
  429. self.label = _("Remove user password")
  430. self.help = _("delete account password")
  431. class VariableUrUnixHash(HashHelper, ReadonlyVariable):
  432. """
  433. Хэш пароля
  434. """
  435. source = "unix.ur_unix_pw"
  436. class VariableUrUnixUserObject(UnixUserHelper, UnixActionHelper,
  437. ReadonlyVariable):
  438. """
  439. Объект данных пользователя
  440. """
  441. def get_exists(self):
  442. login = self.Get('ur_unix_login')
  443. if login:
  444. return self.search_ldap_user_name(login) or ""
  445. return ""
  446. class VariableUrUnixShell(ExistsUserHelper, UnixActionHelper, Variable):
  447. """
  448. Командная оболочка по умолчанию для пользователя
  449. """
  450. attribute = "shell"
  451. opt = ("-s", "--shell")
  452. metavalue = "SHELL"
  453. def init(self):
  454. self.label = _("Shell")
  455. self.help = _("account's login shell")
  456. def get_new(self):
  457. return "/bin/bash"
  458. class VariableUrUnixVisibleSet(ExistsUserHelper, UnixActionHelper, Variable):
  459. """
  460. Виден ли пользователь
  461. """
  462. attribute = "visible"
  463. type = "boolauto"
  464. opt = ("-v", "--visible")
  465. def init(self):
  466. self.label = _("Visible")
  467. self.help = _("manage account visibility")
  468. def get_new(self):
  469. return "on"
  470. def get_exists(self):
  471. return "auto"
  472. class VariableUrUnixLockSet(ExistsUserHelper, UnixActionHelper, Variable):
  473. """
  474. Виден ли пользователь
  475. """
  476. attribute = "lock"
  477. type = "boolauto"
  478. opt = ("-l", "--lock")
  479. def init(self):
  480. self.label = _("Locked")
  481. self.help = _("lock account")
  482. def get(self):
  483. return "auto"
  484. class VariableUrUnixVisibleFlag(UnixUserHelper, ReadonlyVariable):
  485. """
  486. Значение используемое для шаблона
  487. """
  488. def get(self):
  489. return self.visible_to_flag(self.GetBool('ur_unix_visible_set'))
  490. class VariableUrUnixLockFlag(UnixUserHelper, ReadonlyVariable):
  491. """
  492. Значение используемое для шаблона
  493. """
  494. def get(self):
  495. return self.lock_to_flag(self.GetBool('ur_unix_lock_set'))
  496. class VariableUrUnixNextUid(LdapMaxHelper, ReadonlyVariable):
  497. """
  498. Следующий свободный Uid
  499. """
  500. base_dn = "{ld_unix_users_dn}"
  501. search_filter = "uid=*"
  502. attr = "uidNumber"
  503. def get(self):
  504. value = self.get_max()
  505. if value is None:
  506. return self.Get('ur_unix_min_uid')
  507. else:
  508. return str(value + 1)
  509. class VariableUrUnixMinUid(Variable):
  510. """
  511. Минимальный uid
  512. """
  513. type = "int"
  514. value = "10000"
  515. class VariableUrUnixUserCount(UnixUserHelper, UnixActionHelper,
  516. ReadonlyVariable):
  517. """
  518. Количество пользователей
  519. """
  520. type = "int"
  521. def get_exists(self):
  522. return len(self.ldap_user_list())
  523. class VariableClUnixUserAliases(ReadonlyVariable):
  524. """
  525. Алиасы для переменных
  526. """
  527. type = "table"
  528. value = [
  529. # ('login', 'ur_unix_login'),
  530. ('uid', 'ur_unix_uid'),
  531. ('gid', 'ur_unix_primary_group'),
  532. ('comment', 'ur_unix_comment'),
  533. ('lock', 'ur_unix_lock_set'),
  534. ('visible', 'ur_unix_visible_set'),
  535. ('groups', 'ur_unix_groups'),
  536. ('home', 'ur_unix_home_path'),
  537. ('shell', 'ur_unix_shell'),
  538. ('password', 'ur_unix_pw_set'),
  539. ]
  540. class VariableClUnixUserFields(FieldsHelper, Variable):
  541. """
  542. Список полей для вывода данных группы
  543. """
  544. alias_variable = "cl_unix_user_aliases"
  545. class VariableClUnixUserShowFields(ShowFieldsHelper, ReadonlyVariable):
  546. """
  547. Список переменных полей при отображении списка групп
  548. """
  549. alias_variable = "cl_unix_user_aliases"
  550. source_variable = "cl_unix_user_fields"
  551. class VariableClUnixCreateGroupSet(UnixGroupHelper, ReadonlyVariable):
  552. """
  553. Нужно ли создавать primary группу или она уже существует
  554. """
  555. def get(self):
  556. group_name = self.Get('ur_unix_primary_group')
  557. if self.search_ldap_group("cn={0}".format(group_name)):
  558. return "off"
  559. return "on"
  560. class VariableUrUnixUserShow(UnixUserHelper, UnixActionHelper, Variable):
  561. """
  562. Фильтр на login
  563. """
  564. type = "choiceedit"
  565. opt = ["ur_unix_user_show"]
  566. metavalue = "USER"
  567. def init(self):
  568. self.label = _("Login")
  569. self.help = _("show user")
  570. def get(self):
  571. return ""
  572. def choice_exists(self):
  573. try:
  574. return [("", "")] + self.ldap_user_list()
  575. except LDAPConnectError as s:
  576. raise VariableError(str(s))
  577. def check_exists(self, value):
  578. if value:
  579. if not self.search_ldap_user_name(value):
  580. raise VariableError(_("%s user not found") % value)
  581. def raiseWrongChoice(self, name, choiceVal, value, error):
  582. raise VariableError(_("Wrong user name"))