# -*- coding: utf-8 -*- # Copyright 2016 Mir Calculate. 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 sys from os import path from calculate.lib.cl_ldap import LDAPConnectError from calculate.lib.datavars import (ReadonlyVariable, Variable, VariableError, PasswordError) from calculate.ldap.variables.helpers import (HashHelper, LdapMaxHelper) from calculate.unix.variables.helpers import (UnixUserHelper, UnixGroupHelper, ExistsUserHelper, ShowFieldsHelper, FieldsHelper, UnixActionHelper) from .action import Actions import re _ = lambda x: x from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate) setLocalTranslate('cl_unix3', sys.modules[__name__]) __ = getLazyLocalTranslate(_) class VariableUrUnixLogin(UnixUserHelper, UnixActionHelper, Variable): """ Логин настраиваемого пользователя """ untrusted = True opt = ("ur_unix_login",) metavalue = "USER" def init(self): self.label = _("Login") self.help = _("set user login") def get_new(self): return "" def get_exists(self): return self.Get('ur_unix_login_exists') def check_new(self, value): if not value: raise VariableError(_("You should specify login")) if not re.match("^[a-zA-Z_]([a-zA-Z0-9_ -]*[a-zA-Z0-9_-])?$", value): raise VariableError(_("Wrong user login")) if self.search_ldap_user_name(value): raise VariableError(_("User %s already exists" % value)) if self.search_system_user_name(value): raise VariableError( _("User %s already exists in /etc/passwd") % value) class VariableUrUnixLoginExists(UnixUserHelper, UnixActionHelper, Variable): """ Логин настраиваемого пользователя """ type = "choice" opt = ("ur_unix_login_exists",) metavalue = "USER" untrusted = True guitype = "readonly" def init(self): self.label = _("Login") self.help = _("set user login") def get_new(self): return "" def get_exists(self): return "" def choice_exists(self): return ((user.username, "%s (%s)" % (user.username, user.comment)) for user in self.iterate_ldap_user("uid=*")) def raiseWrongChoice(self, name, choiceVal, value, error): if not value: raise VariableError(_("Please specify user login")) else: raise VariableError(_("%s user not found") % value) class VariableUrUnixBaseDir(Variable): """ Базовая директория для нового пользователя """ value = "/home" opt = ('-b', '--base-dir') metavalue = "BASE_DIR" def init(self): self.label = _("Base directory") self.help = _("base directory for the home directory of new account") class VariableUrUnixComment(ExistsUserHelper, UnixActionHelper, Variable): """ Описание учётной записи """ attribute = "comment" value_format = "{ldap.ld_base_root.capitalize()} user" opt = ('-c', '--comment') metavalue = "COMMENT" def init(self): self.label = _("Full name") self.help = _("set fullname of the account") def get_new(self): return "" # self._value_formatter.format(self.value_format, self.Get) class VariableUrUnixHomePath(ExistsUserHelper, UnixActionHelper, Variable): """ Путь до домашней директории """ value_format = "{unix.ur_unix_base_dir}/{unix.ur_unix_login}" opt = ('-d', '--home-dir') metavalue = "HOME_DIR" check_after = ["ur_unix_login"] def init(self): self.label = _("Home directory") self.help = _("set home directory of the account") def get_exists(self): return self.Get('ur_unix_home_path_exists') def get_new(self): return self._value_formatter.format(self.value_format, self.Get) def check_exists(self, value): if "," in value: raise VariableError(_("Wrong home directory")) if not value.startswith('/'): raise VariableError(_("Home directory path must be absolutly")) class VariableUrUnixHomePathExists(ExistsUserHelper, UnixActionHelper, ReadonlyVariable): """ Путь до домашней директории """ attribute = "homedir" class VariableUrUnixHomePathMove(Variable): """ Перемещать домашнуюю пользовательскую директорию """ type = "bool" opt = ('-m', '--move-home') value = "off" check_after = ["ur_unix_home_path", "ur_unix_home_path_exists"] def init(self): self.label = _("Move home directory") self.help = _("move contents of the home directory to the new location") def check_on(self): new_path = self.Get('ur_unix_home_path') old_path = self.Get('ur_unix_home_path_exists') if new_path == old_path: raise VariableError(_("You should change home directory")) if path.exists(new_path): raise VariableError( _("New home directory %s exists") % new_path) if not path.exists(old_path): raise VariableError( _("Previous home directory %s not found") % old_path) class VariableClUnixGroupDefault(Variable): """ Основная группа пользователя по умолчанию """ value = "domain" class VariableUrUnixPrimaryGroup(ExistsUserHelper, UnixGroupHelper, UnixActionHelper, Variable): """ ID основной группы """ attribute = "gid" type = "choiceedit" opt = ('-g', '--gid') metavalue = "GROUP" @property def domain_group(self): return self.Get('cl_unix_group_default') def init(self): self.label = _("Primary group") self.help = _("set name or ID of primary group of the account " "('default' value for create default group)") def get_new(self): return self.domain_group def get_exists(self): value = str(ExistsUserHelper.get_exists(self)) if value: return str(self.gid_to_name(value)) def set(self, value): return str(self.gid_to_name(value)) def choice_new(self): return ([(self.domain_group, self.domain_group)] + self.ldap_group_list()) def choice_exists(self): return self.ldap_group_list() def check_new(self, value): if not value: raise VariableError(_("You should specify primary group ID")) def check_exists(self, value): if not value: raise VariableError(_("You should specify primary group ID")) if value: self.check_group(value) def raiseWrongChoice(self, name, choiceVal, value, error): raise VariableError(_("Group %s not found") % value) class VariableUrUnixGid(UnixGroupHelper, ReadonlyVariable): """ ID основной группы пользователя """ type = "int" def get(self): group_name = self.Get('ur_unix_primary_group') group = self.search_ldap_group_name(group_name) if group: return str(group.gid) else: return self.Get('ur_unix_next_gid') class VariableUrUnixUid(UnixUserHelper, UnixActionHelper, Variable): """ UID пользователя """ type = "int" opt = ('-u', '--uid') metavalue = "UID" value = "" def init(self): self.label = _("User ID") self.help = _("set user ID of the account") def get_new(self): return self.Get('ur_unix_next_uid') def get_exists(self): login = self.Get('ur_unix_login') if login: return str(self.search_ldap_user_name(login).uid) def check_new(self, value): user = self.search_ldap_user_id(value) if user: raise VariableError(_("Uid %s is used by user %s") % (user.uid, user.username)) user = self.search_system_user_id(value) if user: raise VariableError(_("Uid %s is used by system user %s") % (user.uid, user.username)) class VariableUrUnixGroups(UnixGroupHelper, UnixActionHelper, Variable): """ Список груп """ type = "choiceedit-list" opt = ("-G", "--groups") metavalue = "GROUPS" value = [] def init(self): self.label = _("Supplimentary groups") self.help = _("set list of supplementary groups of the account") def set(self, value): return map(self.gid_to_name, value) def get_exists(self): return self.Get('ur_unix_groups_exists') def choice(self): return self.ldap_group_list() def check(self, value): for group in value: self.check_group(group) class VariableUrUnixGroupsExists(UnixGroupHelper, UnixActionHelper, Variable): """ Список груп """ type = "list" value = [] # def get_bylogin(self, login, obj): # return [x.group_name for x in # self.iterate_ldap_group("memberUid=%s" % login)] def get_exists(self): login = self.Get('ur_unix_login') if login: return [x.group_name for x in self.iterate_ldap_group("memberUid=%s" % login)] return [] class VariableUrUnixGroupsAdd(UnixGroupHelper, UnixActionHelper, Variable): """ Список групп в которые необходимо добавить пользователя """ type = "choiceedit-list" guitype = "hidden" opt = ("-a", "--append") metavalue = "GROUPS" value = [] def init(self): self.label = _("Include to groups") self.help = _("include user into groups") def set(self, value): return map(self.gid_to_name, value) def get_exists(self): exists_groups = set(self.Get('ur_unix_groups_exists')) replace_group = set(self.Get('ur_unix_groups')) return sorted(list(replace_group - exists_groups)) def choice_exists(self): login = self.Get('ur_unix_login') if login: exists_groups = self.Get('ur_unix_groups_exists') return (x for x in self.ldap_group_list() if x[0] not in exists_groups) return [] def check_exists(self, value): exists_groups = self.Get('ur_unix_groups_exists') replace_groups = self.Get('ur_unix_groups') if set(exists_groups) != set(replace_groups): raise VariableError(_( "Appending user to groups unavailable " "with the replace groups using")) login = self.Get('ur_unix_login') groups = self.ldap_group_names() failed = [x for x in value if x not in groups] if failed: raise VariableError( _("Wrong groups {groups}").format( groups=", ".join(failed))) self.check_special(value, exists_groups, login) def check_special(self, value, exists_groups, login): already_exists = [x for x in value if x in exists_groups] if already_exists: raise VariableError( _("User {user} already exist in groups {groups}").format( groups=", ".join(already_exists), user=login)) def humanReadable(self): if not self.Get(): return _("Not change") class VariableUrUnixGroupsDel(VariableUrUnixGroupsAdd): """ Список групп из которых необходимо исключить пользователя """ type = "choiceedit-list" opt = ("-r", "--remove") guitype = "hidden" metavalue = "GROUPS" value = [] def init(self): self.label = _("Exclude from groups") self.help = _("exclude user from groups") def get_exists(self): exists_groups = set(self.Get('ur_unix_groups_exists')) replace_groups = set(self.Get('ur_unix_groups')) return sorted(list(exists_groups - replace_groups)) def choice_exists(self): login = self.Get('ur_unix_login') if login: exists_groups = self.Get('ur_unix_groups_exists') return (x for x in self.ldap_group_list() if x[0] in exists_groups) return [] def check_special(self, value, exists_groups, login): not_exists = [x for x in value if x not in exists_groups] if not_exists: raise VariableError( _("User {user} is not exist in groups {groups}").format( groups=", ".join(not_exists), user=login)) class VariableUrUnixSkel(Variable): """ Skel директория """ opt = ("-k", "--skel") metavalue = "SKEL_DIR" value = "/etc/skel" def init(self): self.label = _("Skeleton directory") self.help = _("set skeletion directory for new account") class VariableUrUnixCreateHomeSet(Variable): """ Создавать домашнюю директорию пользователю """ type = "bool" opt = ("-m", "--create-home") value = "off" check_after = ["ur_unix_home_path"] def init(self): self.label = _("Create home directory") self.help = _("create the user's home directory") def check_on(self): home_path = self.Get('ur_unix_home_path') if path.exists(home_path): raise VariableError( _("Home directory %s already exists") % home_path) class VariableUrUnixPw(Variable): """ Пароль пользователя """ type = "password" opt = ("-p", "--password") value = "" untrusted = True metavalue = "PASSWORD" check_after = ["ur_unix_pw_delete_set", 'ur_unix_lock_set'] def init(self): self.label = _("Password") self.help = _("set user password") def check(self, value): delete_pw = self.GetBool('ur_unix_pw_delete_set') change_lock = self.GetBool('ur_unix_lock_set') if (self.Get('cl_unix_action') == Actions.Passwd and not delete_pw and change_lock is None and not value): raise PasswordError(_("Specify user password")) if self.Get('cl_unix_action') in (Actions.Passwd, Actions.UserMod): if self.Get('ur_unix_pw_delete_set') == 'on' and value: raise VariableError(_("Can not use remove and " "set the password options together")) class VariableUrUnixPwSet(UnixActionHelper, UnixUserHelper, ReadonlyVariable): """ Указан ли пароль у пользователя """ type = "bool" def init(self): self.label = _("Password") def get_exists(self): username = self.Get('ur_unix_login') pw = self.get_password_hash(username) if pw and pw != self.DeletedPassword: return "on" else: return "off" class VariableUrUnixPwDeleteSet(Variable): """ Удалить пароль пользователя """ type = "bool" value = "off" opt = ("--delete-password",) def init(self): self.label = _("Remove user password") self.help = _("delete the password for the named account") class VariableUrUnixHash(HashHelper, ReadonlyVariable): """ Хэш пароля """ source = "unix.ur_unix_pw" class VariableUrUnixUserObject(UnixUserHelper, UnixActionHelper, ReadonlyVariable): """ Объект данных пользователя """ def get_exists(self): login = self.Get('ur_unix_login') if login: return self.search_ldap_user_name(login) or "" return "" class VariableUrUnixShell(ExistsUserHelper, UnixActionHelper, Variable): """ Командная оболочка по умолчанию для пользователя """ attribute = "shell" opt = ("-s", "--shell") metavalue = "SHELL" def init(self): self.label = _("Shell") self.help = _("login shell of the account") def get_new(self): return "/bin/bash" class VariableUrUnixVisibleSet(ExistsUserHelper, UnixActionHelper, Variable): """ Виден ли пользователь """ attribute = "visible" type = "boolauto" opt = ("-v", "--visible") def init(self): self.label = _("Visible") self.help = _("set visible of the account") def get_new(self): return "on" def get_exists(self): return "auto" class VariableUrUnixLockSet(ExistsUserHelper, UnixActionHelper, Variable): """ Виден ли пользователь """ attribute = "lock" type = "boolauto" opt = ("-l", "--lock") def init(self): self.label = _("Locked") self.help = _("lock the account") def get(self): return "auto" class VariableUrUnixVisibleFlag(UnixUserHelper, ReadonlyVariable): """ Значение используемое для шаблона """ def get(self): return self.visible_to_flag(self.GetBool('ur_unix_visible_set')) class VariableUrUnixLockFlag(UnixUserHelper, ReadonlyVariable): """ Значение используемое для шаблона """ def get(self): return self.lock_to_flag(self.GetBool('ur_unix_lock_set')) class VariableUrUnixNextUid(LdapMaxHelper, ReadonlyVariable): """ Следующий свободный Uid """ base_dn = "{ld_unix_users_dn}" search_filter = "uid=*" attr = "uidNumber" def get(self): value = self.get_max() if value is None: return self.Get('ur_unix_min_uid') else: return str(value + 1) class VariableUrUnixMinUid(Variable): """ Минимальный uid """ type = "int" value = "10000" class VariableUrUnixUserCount(UnixUserHelper, UnixActionHelper, ReadonlyVariable): """ Количество пользователей """ type = "int" def get_exists(self): return len(self.ldap_user_list()) class VariableClUnixUserAliases(ReadonlyVariable): """ Алиасы для переменных """ type = "table" value = [ # ('login', 'ur_unix_login'), ('uid', 'ur_unix_uid'), ('gid', 'ur_unix_primary_group'), ('comment', 'ur_unix_comment'), ('lock', 'ur_unix_lock_set'), ('visible', 'ur_unix_visible_set'), ('groups', 'ur_unix_groups'), ('home', 'ur_unix_home_path'), ('shell', 'ur_unix_shell'), ('password', 'ur_unix_pw_set'), ] class VariableClUnixUserFields(FieldsHelper, Variable): """ Список полей для вывода данных группы """ alias_variable = "cl_unix_user_aliases" class VariableClUnixUserShowFields(ShowFieldsHelper, ReadonlyVariable): """ Список переменных полей при отображении списка групп """ alias_variable = "cl_unix_user_aliases" source_variable = "cl_unix_user_fields" class VariableClUnixCreateGroupSet(UnixGroupHelper, ReadonlyVariable): """ Нужно ли создавать primary группу или она уже существует """ def get(self): group_name = self.Get('ur_unix_primary_group') if self.search_ldap_group("cn={0}".format(group_name)): return "off" return "on" class VariableUrUnixUserShow(UnixUserHelper, UnixActionHelper, Variable): """ Фильтр на login """ type = "choiceedit" opt = ["ur_unix_user_show"] metavalue = "USER" def init(self): self.label = _("Login") self.help = _("show user") def get(self): return "" def choice_exists(self): try: return [("", "")] + self.ldap_user_list() except LDAPConnectError as s: raise VariableError(str(s)) def check_exists(self, value): if value: if not self.search_ldap_user_name(value): raise VariableError(_("%s user not found") % value)