Как стать автором
Обновить

Автоматизация создания пользователей или как я исключил себя из кадровой цепочки

Итак, я сотрудник бюджетной организации с достаточно объёмной для такого типа учреждения IT инфраструктурой и достаточно большим штатом сотрудников. Каждый приход сотрудника сопровождается заведением нового пользователя в AD и выдачу ему логина и пароля, что для меня просто рутина и отвлекает от мыслей о вселенной. Так же присутствует человеческий фактор, меня может не быть на месте, я могу опечататься при создании. Да и ко всему у нас имелась достаточно не безопасная схема - всем выдавался одинаковый временный пароль. Всё это сподвигло меня на написание скрипта, который будет получать данные из 1С ЗУП, создавать на основе этих данных пользователя в AD и высылать эти данные на WathsApp уже сотруднику, причём пароль случайно сгенерированный. Вообще есть готовые обработки для 1С, позволяющие исполнить этот функционал, но они либо платные, либо не работающие с моей конфигурацией, а программист 1С из меня не очень. Однако выгрузка в 1С есть безо всякого изменения кода. Итак, поехали по пунктам.

1. Создадим отчёт и автоматическую выгрузку его. В моей версии конфигурации это выглядит так: кадровые отчёты - персональные данные сотрудников, выбираем настройку отчёта и указываем поле ФИО, номер телефона и дату приёма на работу (указываем текущую дату, чтобы не экспортировать тех кого уже приняли на работу, в режиме настройки отчёта нельзя выбрать чтобы каждый день была сегодняшняя дата, это можно настроить только в конфигураторе, но пока остановимся на просто крайней дате, дальше объясню почему). Далее настроим выгрузку отчёта, это настраивается там же где отправка на почту, значок в виде конверта. Я выбрал выгрузку в сетевую папку, обратите внимание, что для папки должны быть права на запись тех пользователей, которые работают в базе ибо файловый вариант базы автоматически отправляет отчёты, только если запущен клиент. Отчёт лучше формировать в txt. Убедившись, что отчёт сформирован и выгружен, можно переходить ко второму пункту - это скрипт на Power shell.

2. Скрипт сначала преобразует выгруженный файл в читаемый для PS, убирает лишние символы и пересохраняет, затем считывает снова уже в правильном формате, преобразует ФИО с помощью функции транслитерации, создаёт пользователя согласно необходимым критериям (в данном случае для создания логина используется первая буква имени, точка, фамилия), пароль генерируется с помощью функции генерации случайных символов, функция настраиваемая, по количеству символов и содержанию букв, цифр и спец символов (у меня спец символы не используются, многие пользователи не знают, где они на клавиатуре). В цикле создания пользователя используется проверка на выполнение команды, если пользователя нет и команда создания выполнена запускается скрипт на питоне, отправляющий сообщение, если пользователь есть и команда не выполнена, соответственно скрипт прерывается. Это позволяет не редактировать дату приёма в выгрузке 1с, имеющийся пользователь просто не создастся. Прерывание скрипта вызвано тем, что скрипт питона после работы не завершает процесс питона и следующее выполнение скрипта не срабатывает. Здесь жду каких-то подсказок ибо у меня нет мыслей на этот счёт, я пробовал и через команду kill, и пр., не срабатывает.

Сам скрипт собственно, с комментами:

Import-Module activedirectory 	#строка говорит сама за себя
function global:Translit {		 #начало функции транслитерации
param([string]$inString)
$Translit = @{
[char]'а' = "a"
[char]'А' = "A"
[char]'б' = "b"
[char]'Б' = "B"
[char]'в' = "v"
[char]'В' = "V"
[char]'г' = "g"
[char]'Г' = "G"
[char]'д' = "d"
[char]'Д' = "D"
[char]'е' = "e"
[char]'Е' = "E"
[char]'ё' = "yo"
[char]'Ё' = "Yo"
[char]'ж' = "zh"
[char]'Ж' = "Zh"
[char]'з' = "z"
[char]'З' = "Z"
[char]'и' = "i"
[char]'И' = "I"
[char]'й' = "j"
[char]'Й' = "J"
[char]'к' = "k"
[char]'К' = "K"
[char]'л' = "l"
[char]'Л' = "L"
[char]'м' = "m"
[char]'М' = "M"
[char]'н' = "n"
[char]'Н' = "N"
[char]'о' = "o"
[char]'О' = "O"
[char]'п' = "p"
[char]'П' = "P"
[char]'р' = "r"
[char]'Р' = "R"
[char]'с' = "s"
[char]'С' = "S"
[char]'т' = "t"
[char]'Т' = "T"
[char]'у' = "u"
[char]'У' = "U"
[char]'ф' = "f"
[char]'Ф' = "F"
[char]'х' = "h"
[char]'Х' = "H"
[char]'ц' = "c"
[char]'Ц' = "C"
[char]'ч' = "ch"
[char]'Ч' = "Ch"
[char]'ш' = "sh"
[char]'Ш' = "Sh"
[char]'щ' = "sch"
[char]'Щ' = "Sch"
[char]'ъ' = ""
[char]'Ъ' = ""
[char]'ы' = "i"
[char]'Ы' = "I"
[char]'ь' = ""
[char]'Ь' = ""
[char]'э' = "e"
[char]'Э' = "E"
[char]'ю' = "u"
[char]'Ю' = "U"
[char]'я' = "ia"
[char]'Я' = "Ia"
}
$outCHR=""
foreach ($CHR in $inCHR = $inString.ToCharArray())
{
if ($Translit[$CHR] -cne $Null )
{$outCHR += $Translit[$CHR]}
else
{$outCHR += $CHR}
}
Write-Output $outCHR
} 							#конец функции транслитерации
Function GenPassword ($PasswordLength) 	#начало функции генерации пароля
{
    $rand = New-Object System.Random
    $PassNotCheck = $true
    while ($PassNotCheck)
    {
       $Password = $null
        1..$PasswordLength | % { 
            switch (Get-Random -Minimum 1 -Maximum 4)
            {
                1 {$Password = $Password + [char]$rand.next(65,91)}  #A-Z
               2 {$Password = $Password + [char]$rand.next(48,58)}  #0-9
                3 {$Password = $Password + [char]$rand.next(97,123)} #a-z
            }
        }   
    if (($Password -match "[0-9]") -and ($Password -cmatch "[a-z]") -and ($Password -cmatch "[A-Z]")) {$PassNotCheck = $false}
    }
    Write-Output $Password
} 								#конец фунции генерации пароля
Remove-Item \\fs01\wallp$\Выгрузка\1.csv 		#удаляем предыдущий файл
Rename-Item "\\fs01\wallp$\Выгрузка\*.txt" "1.csv"  #переименовываем файл выгрузки
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "Сотрудник", "Surname Name Fathername"} | set-content \\fs01\wallp$\Выгрузка\1.csv 	#заменяем слова, сформированные отчётом 1с нужными нам
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "Телефон мобильный", "Tel"} | set-content \\fs01\wallp$\Выгрузка\1.csv 			#Заменяем столбец телефон
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\(", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#убираем лишние скобки, которые могли быть в отчёте, обратите внимание как они обособлены
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\)\ ", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "-", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv 							#убираем тире
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "`t8", " +7"} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#убираем восьмёрку с табуляцией и заменяем её на читаемую для скрипта +7, обратите внимание на символ табуляции
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\+7 ", "+7"} | set-content \\fs01\wallp$\Выгрузка\1.csv 						# пробелы лишние тоже
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "`t", " "} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#лишняя табуляция
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace " ", ","} | set-content \\fs01\wallp$\Выгрузка\1.csv -encoding utf8 				#в самый последний момент заменяем пробелы запятыми, чтобы они стали разделителями и указываем кодировку 
$H = Get-Date -Format "HH" 				#переменная часа для передачи в питон
$M = Get-Date -Format "mm" 				#переменная минут для питона
Import-Csv "\\fs01\wallp$\Выгрузка\1.csv" | ForEach-Object {		 #начало прочтения уже отредактированного файла и перебор
$ou = 'OU=Test,OU=Сотрудники,DC=panspb,DC=local' 				#папка в AD куда будут создаваться пользователи
$Temppass = GenPassword -PasswordLength 7 					#генерируем в переменную пароль длинной в 7 символов
$sa = translit($_.name[0]) 								#переводим первую букву имени, первая это нулевая, т.к. строка это массив из символов, из кириллицы в латиницу и записываем в переменную
$sa = $sa+"." 										#прибавляем точку к имени
$su = translit($_.surname) 								#переводим фамилию
$sa = $sa + $su 										#склеиваем имя и фамилию и получаем будущий логин
$NA = $_.surname + " " + $_.name + " " + $_.fathername 			#склеиваем фио и получаем отображаемое имя
New-ADUser -Name $NA ` 									#создаём пользователя с переменной, в которой указан фио
-GivenName $_.name ` 									#добавляем имя
-Surname $_.surname ` 									#фамилию
-SamAccountName $sa ` 									#логин
-AccountPassword (ConvertTo-SecureString $temppass -AsPlainText -force) -Enabled $true ` #пароль
-Path $ou ` 										#директория в AD 
-DisplayName $na ` 									#отображаемое имя
-UserPrincipalName ($sa + "@panspb.local") ` 					#полное доменное имя
-CannotChangePassword 0 ` 								#разрешено менять пароль
-ChangePasswordAtLogon 1 								#требование смены пароля
if($?){ 											#проверка выполнения команды
C:\Python37\python.exe \\fs01\wallp$\Выгрузка\telsh.py --tel=$_.tel --t=$sa,$Temppass --h=$H --m=$M 			#запуск скрипта питона, в который передаётся номер телефона, логин и пароль в качестве текста и время отправки сообщения 
Add-ADGroupMember -Identity "Сотрудники" -Members $sa 			#добавление в группу безопасности, если требуется
exit		 #прерывание скрипта
}
}

Далее переходим к самому скрипту питона для отправки сообщения.

3. Скрипт отправки сообщения в WhatsApp.

Перед тем как работать со скриптом нужно установить сам питон естественно и установить т.н. пип, на этом я не буду заострять внимение, т.к. для каждой системы и каждого питона своя инструкция. После установки пипа нужно установить библиотеку piwhatkit. После этих действий можно переходить к ватсапу, на Пк с которого выполняется скрипт должен быть запущен WhatsApp Web и должна быть синхронизация с аккаунтом от имени которого будут отправляться сообщения, это может быть как корп акк, так и личный.

import argparse 											#это библиотека для передачи параметров из вне
parser = argparse.ArgumentParser(description='A tutorial of argparse!')
parser.add_argument("--tel") 									#аргумент телефона
parser.add_argument("--t") 									#аргумент текста
parser.add_argument("--h") 									#аргумент часа
parser.add_argument("--m") 									#аргумент минут
args = parser.parse_args() 									#массив аргументов
tel = args.tel 											#записываем полученный аргумент телефона в переменную
t = args.t 												#записываем аргумент текста
h = int(args.h) 											#записываем аргумент часа и переводим его в числовой формат, т.к. приходит он как строка
m = int(args.m) 											#то же самое для минут
m = m + 2 												#необходимо увеличить минуту на 2, чтобы дать время на запуск браузера и отправку сообщения
import pywhatkit as kit 									#импортруем библиотеку для отправки
kit.sendwhatmsg(tel, t, h, m) 								#отправляем сообщение с переданными параметрам
exit()

Нужно отметить, что есть нюанс отправки сообщения, не всегда эта билиотека может захватить окно браузера, но об этом лучше почитать непосредственно о самой библиотеке.

Собственно задача выполнена, сотрудник отдела кадров добавляет нового сотрудника в ЗУП, срипт отсылает учётные данные человеку на WhatsApp, системный администратор в этом процессе не участвует. Я добавил этот скрипт в планировщик с периодичностью в 30 минут, второй строкой я добавил закрытие браузера, т.к. каждое новое сообщение отправляется из новой вкладки. Можно в скрипт добавить строку создания почты в Эксчейндже, но у меня для этого отдельный скрипт. На будущее я запланировал синхронизацию с ПО LMS школа, это спец ПО для образовательных учреждений, если у кого-нибудь есть по этому готовые наработки, просьба поделиться.

Жду комментариев и предложений по оптимизации, надеюсь кому-то пригодятся моти строки.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.