You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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