# -*- 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 ,
VariableInterface )
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 UserNameHelper ( VariableInterface ) :
"""
Вспомогательный объект для проверки имени группы
"""
def check_user_name ( self , uname ) :
if len ( uname ) > 32 :
raise VariableError ( _ ( " Wrong user name length " ) )
if " : " in uname :
raise VariableError ( _ ( " Wrong user name " ) )
class VariableUrUnixLogin ( UserNameHelper , 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 ( _ ( " Please specify the login " ) )
self . check_user_name ( value )
if value == " list " :
raise VariableError ( _ ( " List is used as keyword " ) )
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 is already 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 the 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 new account ' s home " )
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 full name for 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 for 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 ( _ ( " Non-existing home directory " ) )
if not value . startswith ( ' / ' ) :
raise VariableError ( _ ( " Home must have an absolute path " ) )
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 home conents to 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 ( _ ( " Please change home directory " ) )
if path . exists ( new_path ) :
raise VariableError (
_ ( " New home directory %s already exists " ) % new_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 for account "
" ( ' default ' creates a 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 ( _ ( " Please specify the primary group ID " ) )
def check_exists ( self , value ) :
if not value :
raise VariableError ( _ ( " Please specify the 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 " )
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 {userid} is used by user {username} " ) . format (
userid = user . uid , username = user . username ) )
user = self . search_system_user_id ( value )
if user :
raise VariableError (
_ ( " UID {userid} is used by system user {username} " ) . format (
userid = user . uid , username = user . username ) )
class VariableUrUnixGroups ( UnixGroupHelper , UnixActionHelper , Variable ) :
"""
Список груп
"""
type = " choiceedit-list "
opt = ( " -G " , " --groups " )
metavalue = " GROUPS "
value = [ ]
def init ( self ) :
self . label = _ ( " Supplementary groups " )
self . help = _ ( " set list of supplementary groups for 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 ( _ (
" You cannot add user to group and replace their groups " ) )
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 _ ( " Do 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 (
_ ( " No user {user} was found 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 = _ ( " use alternative skeleton directory " )
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 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 ( _ ( " You cannot use remove and password "
" setup 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 account password " )
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 = _ ( " account ' s login shell " )
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 = _ ( " manage account visibility " )
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 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 )
def raiseWrongChoice ( self , name , choiceVal , value , error ) :
raise VariableError ( _ ( " Wrong user name " ) )