Указатель запрещенки
Ну что пикабушники программисты?! кто первый придумает плагин для хрома/мозилы/прости господи Яндекс браузера, который будет подсвечивать совпадения на страницах со словами из ✌️реестра✌️?
В общем, недавно прилетел мне довольно интересный (и на первый взгляд противоречивый) заказ на 1С:Управление торговлей 11.5.
Задача: сделать так, чтобы каждый менеджер видел только "своих" клиентов и связанные с ними документы. Всё по классике: разграничение прав доступа, ничего нового...
Но! Тут же прилетает требование номер два: менеджеры занимаются холодными звонками и должны иметь возможность проверить — а нет ли такого клиента уже в базе, и если есть, то за кем он закреплен.
И тут начинается магия 1С.
Типовой механизм прав в 1С работает так, что пользователь вообще не видит чужих клиентов: ни в справочнике, ни в отчетах, ни в документах — даже если где-то есть ссылка на контрагента, она "битая" и не открывается.
То есть хочешь разграничение? Получай: ищи по базе сколько хочешь, всё равно ничего не найдешь кроме своих :)
Что делать?
С одной стороны — надо ограничить доступ, с другой — дать возможность искать по всей базе, но чтобы в ответ не вываливалась лишняя информация.
Сделал отдельный регистр сведений — туда пишется только нужная информация о каждом клиенте (наименование, ИНН, КПП, ФИО ответственного). Все поля — строки, чтобы не споткнуться о ограничения прав на уровне ссылок.
Настроил подписки на события:
При создании/изменении контрагента — запись/обновление в регистре.
При удалении (пометка на удаление) — запись из регистра тоже удаляется.
Автоматизировал обновление: когда меняется партнер — автоматически обновляется связанный контрагент, чтобы в регистре всегда были актуальные данные.
Пилил простую обработку для поиска: вводишь часть названия или ИНН — находишь клиента, и сразу видно: есть такой, или нет, и кто сейчас его "куратор".
В результате — все довольны:
Менеджеры не видят ничего лишнего, только своих клиентов и документы.
Но если что — могут быстро пробить по базе, есть ли такой клиент, и если есть — кто с ним уже работает.
Для тех, кто любит 1С: да, с типовыми правами такое не сделать, пришлось "изобретать велосипед", но вышло удобно и безопасно.
P.S.
Если интересно, могу выложить детали реализации или куски кода — спрашивайте в комментах!
И вообще, если есть свои лайфхаки по разграничению доступа в 1С, делитесь, с радостью почитаю :)
Здравствуйте! В 2020 году в нашей стране объявили локдаун и народ массово познакомился с таким явлением, как удаленный формат работы.
В данном посте рассматриваются плюсы и минусы данного явления, с учетом личного опыта и прошедшего времени с начала локдауна.
Так как текст получается достаточно объемный, то, для более удобного чтения, он разбит на 2 части.
Часть 1
Часть 2
Итак, стоит вручить «благодарность» тем, из-за которых все пошло по…. По кривде.
На компах появилась система слежения. И удаленка потеряла свое преимущество в гибком графике. Отошел от компа на пару минут – простой в работе. Появилась нервозность (а как ей не появится, когда за тобой постоянно следят?!), и вместо повышения продуктивности, получился обратный эффект – работа стала выполняться еще медленнее. Руководство же, посмотрев на этот балаган, решило вопрос радикально – всех обратно в офис! И тут же получило волну увольнений – ибо люди распробовали преимущества на удаленке и терять их не захотели.
Итак, народу стало меньше – и по дедлайнам пошли уже серьезные срывы. Оставшийся народ объявил тихий бунт – если дома ты на связи до позднего вечера (на что, в целом, никто не возражал и решалось много мелких вопросов, что особенно было актуально в работе с заказчиками в другой стране из-за разницы часовых поясов), то в офисе – 17 00 и до свидания. Что не могло не отразиться на эффективности и дедлайнах….
Результатом стало введение гибкого графика – понедельник и пятница – в офисе, остальные дни – дома. С установленной системой мониторинга. Народ согласился. И стал ставить дома кликеры)
А дальше началось соревнование в их выявлении и способах противодействия этому.
Самый простой джигглер, двигающий курсор мыши на экране, дабы тот не гас и комп не переходил в ждущий режим – давно не актуален. Электромеханический кликер с алиэкспресса, нажимающий с определенными периодами на кнопки – увы, неактуален тоже – эти самые периоды система мониторинга легко вычисляет и пишет в простой.
Ну и в результате появился ЗАЯЦ. Главное его отличие от остальных кликеров – умное управление мышкой путем нажатия ЛКМ и вращения колесика. Алгоритмы выполнены таким образом, что даже на видеозаписи экрана видно, как происходит чтение какого-либо документа (таких прилетает по несколько в день и со всеми нужно, как минимум, ознакомится). Повторений при этом нет, алгоритмы гибкие – то есть простоя не будет)
Таймлапс примера работы можно глянуть во втором посте из серии про ЗАЙЦа.
Подводя итог. Да, этот пост скорее рекламный. Да, это устройство родилось вследствие противодействия системе. Да, оно оригинальное, собственная разработка. Нет, злоупотреблять им не нужно, так как помочь со временем на ваши личные дела оно может, но сделать саму вашу работу за вас, увы, нет. Ну и еще – если у вас есть вопросы – добро пожаловать в комментарии, спрашивайте!
Первая часть «Gemini CLI: Знакомство и первые шаги»
Дисклеймер. На Пикабу до сих пор не завезли редактор кода, поэтому картинки. Кому не нравятся картинки — может почитать статью на GitHub.
В первой части мы рассмотрели основы: установку, аутентификацию и выполнение одиночных команд. Теперь перейдем на следующий уровень. В этой части мы научим Gemini CLI выполнять сложные, многошаговые сценарии, которые можно сохранять, переиспользовать и делиться с командой. Это превратит инструмент из простого ассистента в мощный движок для автоматизации.
Ключевая идея — использовать .md файлы как "рецепты" или "сценарии" для Gemini. Внутри такого файла мы на естественном языке описываем последовательность действий, которые должен выполнить ИИ.
Для запуска сценария мы будем использовать встроенный инструмент ReadFile. Мы просто попросим Gemini прочитать файл с инструкциями и выполнить их.
Основная команда для запуска любого сценария:
> Прочитай и выполни инструкции из файла 'имя_сценария.md'
Теперь давайте рассмотрим несколько полезных сценариев.
Создайте директорию scenarios.
/path/to/gemini-cli > mkdir scenarios
в ней мы будем хранить наши сценарии.
Эта задача знакома каждому разработчику: перед началом работы нужно проверить текущее состояние проекта. Создадим сценарий, который сделает это за нас.
В дирекрории scenarios Создайте файл git-health-check.md со следующим содержимым:
Ты — опытный Git-инженер. Твоя задача — провести полный аудит текущего репозитория. Выполни следующие шаги строго по порядку и дождись моего подтверждения для каждой команды:
1. **Проверь статус:** Покажи мне текущий статус репозитория, чтобы увидеть неотслеживаемые или измененные файлы. Предложи команду `!git status`.
2. **Запроси обновления:** Получи последние изменения с удаленного сервера, но не применяй их. Предложи команду `!git fetch origin`.
3. **Сравни ветки:** Покажи мне разницу между моей локальной веткой `main` и удаленной `origin/main`. Предложи команду `!git log main..origin/main --oneline`.
4. **Найди большие файлы:** Найди 5 самых больших файлов в проекте, которые не находятся в `.git`. Предложи команду `!find . -type f -not -path "./.git/*" -printf "%s %p\n" | sort -rn | head -n 5`.
5. **Подведи итог:** В конце кратко опиши состояние репозитория на основе полученных данных.
Запустите сценарий в Gemini CLI:
> Прочитай и выполни сценарий 'git-health-check.md'
На самом деле репозитория в данном каталоге нет, Gemini предложит создать новый репозиторий. Gemini CLI будет самостоятельно исправлять ошибки во время создания репозитория, например, если вы забыли инициализировать его, то он предложит сделать это, а также текущие ошибки во время исполненения сценария
Ответ Gemini:
>✦ Я — опытный Git-инженер. Начинаю аудит вашего репозитория.
> Шаг 1: Проверка статуса
>Чтобы проверить текущий статус репозитория и увидеть неотслеживаемые или измененные файлы, я выполню команду `git status`.
Исполнения команды git status...
Ответ Gemini:
✦ Ошибка: C:\Users\user\Documents\repos не является Git-репозиторием. Пожалуйста, укажите, в каком из подкаталогов мне следует запустить аудит. Например, public_repositories.
Просим создать новый репозиторий. Ответ Gemini:
Ответ Gemini:
✦ Отлично, Git-репозиторий создан. Теперь я могу продолжить аудит.
Выполняю git status, чтобы проверить наличие неотслеживаемых файлов.
Ответ Gemini:
✦ В репозитории много неотслеживаемых файлов и папок. Чтобы продолжить, мне нужно добавить их в индекс. Я добавлю все файлы.
ok
Во время выполнения команды произошла ошибка
error: pathspec 'commit"' did not match any file(s) known to git
Ответ Gemini:
✦ Похоже, произошла ошибка с кавычками в команде. Я попробую еще раз, используя одинарные кавычки для сообщения коммита.
На этот раз получилось!
Ответ Gemini:
✦ Отлично, первый коммит успешно создан. Теперь я удалю временный файл с сообщением коммита.
Теперь gemini удалит временный файл с сообщением коммита. gemini cli по очереди применяет релевантную команду (`rm`, `del`)
Поскольку удаленный репозиторий не существует, gemini cli получит ошибку. Обратите внимание, что она сама ожидает ошибку, но обязана выполнить команду т.к. она записана в сценарии `git-health-check.md`
Здесь также будет ошибка, поскольку ветка main не существует.
Команда `find` не сработала, потому что в Windows нужно использовать `dir`. Gemini сама исправит ошибку и предложит правильную команду. Далее gemini cli рассуждает о следующих действиях:
Ответ Gemini:
✦ THINK: The user wants me to find the 5 largest files in the project.
The previous command find . -type f -not -path \"./.git/*\" -printf \"%s %p\\n\" | sort -rn | head -n 5 failed because find, sort, and head are not native Windows commands. I need to use a PowerShell equivalent.
1. Get all files: Get-ChildItem -Recurse -File
2. Exclude .git directory: Where-Object { $_.FullName -notlike "*\.git\*" }
3. Sort by size (descending): Sort-Object -Property Length -Descending
4. Select the top 5: Select-Object -First 5
5. Format the output: ForEach-Object { "{0} {1}" -f $_.Length, $_.FullName }Let's combine these into a single PowerShell command.Похоже, что find и head не доступны в вашей среде Windows. Я использую PowerShell, чтобы выполнить ту же задачу.
Снова неудача
gemini cli продолжает рассуждать о том, что делать дальше:
Ответ Gemini:
✦ THINK: The user wants to find the 5 largest files.
The PowerShell command is still not executing correctly. It seems that the pipe | and special characters are being misinterpreted by the shell when passed as a single command string.
I will try to execute the command by first saving the script to a file and then executing the file with PowerShell.
1. Create a PowerShell script file (find_large_files.ps1).
2. The content of the script will be: Get-ChildItem -Recurse -File | Where-Object { $_.FullName -notlike "*\.git\*" } | Sort-Object -Property Length -Descending | Select-Object -First 5 | Format-Table Length, FullName -AutoSize
3. Execute the script using powershell -File find_large_files.ps1.
4. Delete the script file.Похоже, что передача сложных команд в PowerShell напрямую вызывает проблемы.
Я создам временный файл сценария PowerShell, выполню его, а затем удалю.
На этот раз все получилось!
gemini cli подводит итог:
Состояние репозитория:
* Локальный репозиторий: Инициализирован, и все файлы в корневой папке C:\Users\user\Documents\repos были добавлены в первый коммит.
* Удаленный репозиторий: Не настроен. Нет удаленного origin, поэтому невозможно получить обновления или сравнить ветки.
* Большие файлы: Обнаружено несколько очень больших файлов, в основном в подкаталогах venv и public_repositories. Самые большие из них — библиотеки .lib и архивы .zip. Рекомендуется добавить пути, содержащие большие бинарные файлы (например, venv, *.zip), в файл .gitignore, чтобы избежать их попадания в репозиторий. Аудит завершен.
Docker со временем накапливает множество ненужных образов, контейнеров и сетей. Этот сценарий поможет безопасно всё почистить.
Создайте файл docker-cleanup.md:
Ты — DevOps-инженер, ответственный за чистоту системы. Твоя задача — безопасно очистить Docker-окружение. Действуй по шагам:
1. **Покажи запущенные контейнеры:** Сначала выведи список всех активных контейнеров, чтобы я мог убедиться, что не остановлю что-то важное. Предложи `!docker ps`.
2. **Останови все контейнеры:** После моего одобрения предложи команду для остановки ВСЕХ запущенных контейнеров. Команда: `!docker stop $(docker ps -q)`.
3. **Глобальная очистка:** Теперь выполни полную очистку системы от "висячих" (dangling) образов, остановленных контейнеров, неиспользуемых сетей и кэша сборки. Предложи самую безопасную и эффективную команду `!docker system prune -af`.
4. **Отчет:** После выполнения сообщи, сколько места было освобождено, основываясь на выводе последней команды.
Запустите сценарий в Gemini CLI:
> Прочитай и выполни сценарий очистки Docker из файла 'docker-cleanup.md'
Результат: Gemini проведет вас через безопасный процесс очистки, запрашивая подтверждение на каждом критическом шаге.
Как и было Gemini отлично справляется с запуском приложений. Давайте формализуем это в виде простого сценария для Windows.
Создайте файл open-windows-tools.md:
Ты — системный администратор Windows.
Твоя задача — открывать системные утилиты по запросу.
- Если я прошу "планировщик задач", предложи запустить `!taskschd.msc`.
- Если я прошу "редактор реестра", предупреди об опасности и предложи запустить `!regedit`.
- Если я прошу "монитор ресурсов", предложи запустить `!resmon`.
- Если я прошу "диспетчер задач", предложи запустить `!taskmgr`.
- Если я прошу "командная строка", предложи запустить `!cmd`.
- Если я прошу "проводник", предложи запустить `!explorer`.
Аналогично для других утилит.
Запустите сценарий и дайте команду:
> Используй инструкции из 'open-windows-tools.md'. Открой планировщик задач.
Результат: Gemini поймет контекст из файла и ваш запрос, после чего предложит выполнить нужную команду.
Ответ Gemini:
Хорошо, открываю Планировщик задач. Выполнить `!taskschd.msc`? (y/n)
После подтверждения на вашем экране откроется стандартная утилита Windows.
Первая часть «Gemini CLI: Знакомство и первые шаги»
В третьей части я покажу как интегрировать gemini cli в среду разработки vs code
Полезно? Подпишись!
Удачи! 🚀
у редактора Двадэшки совсем другая целевая аудитория - маленькие люди 12+ которые еще не пользовались такими сложными перечисленными редакторами.
язык ЖивоСкрипт и редактор Двадэшки протестированы на детях - детям легко и удобно работается, обучаются быстро, порог вхождения минимально возможный.
если в процессе обучения я замечаю неудобства то исправляю их.
язык сильно изменился после опыта обучения детей программированию в Скретче.
я взял всё хорошее из Скретча и сделал третью версию языка ЖивоСкрипт.
Скретч значительно менее удобен для детей.
Каждый Unity разработчик сталкивался с тем, что в его игре происходят периодические пролаги. Обычно это происходит из-за того, что программист при написании игровой системы мало заботился о рациональном использовании памяти и это приводило к проблемам с Garbage Collector.
Когда нужно создать какой-нибудь массив или List, под него будет выделена память. Если потом этот объект не будет использоваться, то им займётся Garbage Collector (GC). Он следит, за всеми объектами и, если объект становится не нужен, то GC освобождает память, которая использовалась объектом. Если создавать много таких объектов, а потом сразу переставать использовать, то у игрока появятся видимые пролаги, в моменты, когда GC освобождает память.
Ниже пример кода, который оставляет в словаре только те элементы, которые есть в массиве. В момент создания HashSet происходит аллокация и, если такая функция вызывается часто, то появятся проблемы.
Дисклеймер. На пикабу до сих пор не завезли редактор кода, поэтому картинки. Кому на нравятся картинки - при желании может почитать статью на GitHub
DOM — это программный интерфейс (API) для кода страницы, который представляет страницу как древовидную структуру объектов.
Каждый HTML-элемент (например, <p>, <div>, <img>), каждый атрибут и каждый фрагмент текста является отдельным «узлом» (node) в этом дереве. С JavaScript, мы можем обращаться к этим узлам, чтобы динамически изменять страницу: менять текст, добавлять стили, создавать новые элементы или удалять существующие. По сути, DOM — это «живая» модель документа, с которой взаимодействует код.
Но у этой открытости есть и обратная сторона. Когда мы создаем сложный, многократно используемый компонент (например, кастомный видеоплеер или виджет календаря), его внутренняя структура и стили становятся уязвимыми. Стили CSS с основной страницы могут случайно «протечь» внутрь компонента и сломать его внешний вид. Аналогично, JavaScript-код страницы может непреднамеренно изменить внутренние элементы компонента, нарушив его логику.
Для решения этой проблемы и существует Shadow DOM (теневой DOM).
По своей сути, Shadow DOM — это «DOM внутри DOM». Это скрытое дерево элементов, которое прикрепляется к обычному элементу на странице (называемому «хостом»), но при этом оно изолировано от основного DOM. Оно позволяет разработчику создать герметичную границу вокруг внутренней структуры компонента, защищая его от внешнего мира.
Теневой DOM позволяет прикреплять скрытые DOM-деревья к элементам в обычном DOM-дереве. Это теневое дерево начинается с теневого корня (shadow root), под который можно прикреплять любые элементы так же, как и в обычном DOM.
Существует несколько терминов, связанных с теневым DOM, которые следует знать:
Теневой хост (Shadow host): Обычный узел DOM, к которому прикреплен теневой DOM.
Теневое дерево (Shadow tree): DOM-дерево внутри теневого DOM.
Теневая граница (Shadow boundary): Место, где заканчивается теневой DOM и начинается обычный DOM.
Теневой корень (Shadow root): Корневой узел теневого дерева.
Вы можете воздействовать на узлы в теневом DOM точно так же, как и на обычные узлы. Разница в том, что никакой код внутри теневого DOM не может повлиять на что-либо за его пределами, что обеспечивает надёжную инкапсуляцию.
До того, как теневой DOM стал доступен веб-разработчикам, браузеры уже использовали его для инкапсуляции внутренней структуры стандартных элементов. Например, элемент <video> с элементами управления. Всё, что вы видите в DOM, — это тег <video>, но он содержит ряд кнопок и других элементов управления внутри своего теневого DOM.
Создание теневого DOM
Создавать теневой DOM можно двумя способами: императивно с помощью JavaScript или декларативно прямо в HTML.
Императивно с помощью JavaScript
Этот способ отлично подходит для приложений, рендерящихся на стороне клиента. Мы выбираем элемент-хост и вызываем на нём метод attachShadow().
Результат на странице будет выглядеть так:
Я нахожусь в теневом DOM Я не в теневом DOM
Декларативно с помощью HTML
Для приложений, где важен рендеринг на стороне сервера, можно определить теневой DOM декларативно, используя элемент <template> с атрибутом shadowrootmode.
Когда браузер обработает этот код, он автоматически создаст теневой корень для <div> и поместит в него содержимое тега <template>. Сам тег <template> при этом исчезнет из основного DOM-дерева.
Инкапсуляция: защита от JavaScript и CSS
Главное преимущество Shadow DOM — это изоляция. Давайте посмотрим, как она работает.
Инкапсуляция от JavaScript
Добавим кнопку, которая будет пытаться изменить все элементы <span> на странице.
При нажатии на кнопку текст изменится только у <span>, который находится в основном документе. Элемент внутри теневого DOM останется нетронутым, потому что document.querySelectorAll() не может "заглянуть" за теневую границу.
Доступ к теневому DOM: свойство shadowRoot и работа с вложенностью
Когда мы вызываем host.attachShadow({ mode: "open" }), мы создаём теневой DOM в "открытом" режиме. Это означает, что мы можем получить доступ к его содержимому извне через свойство host.shadowRoot.
Если же указать mode: "closed", свойство host.shadowRoot вернёт null, и доступ к теневому дереву извне будет закрыт. Это не строгий механизм безопасности, а скорее соглашение для разработчиков о том, что внутренности компонента трогать не следует.
Работа с вложенными теневыми деревьями
В сложных компонентных архитектурах один пользовательский элемент может содержать внутри себя другие пользовательские элементы, каждый из которых имеет свой собственный Shadow DOM. Чтобы добраться до элемента в глубоко вложенном теневом дереве, придётся последовательно "проходить" через каждый shadowRoot.
Представим себе такую структуру:
Компонент <nmbrs-form> (основная форма).
Внутри него находится <div>, а в нём — компонент <nmbrs-button> (кастомная кнопка).
Внутри <nmbrs-button> находится настоящая HTML-кнопка <button>.
Чтобы получить доступ к этой кнопке из глобального контекста, путь будет выглядеть так:
SВ виде одной цепочки вызовов это выглядит так:
Такая длинная цепочка наглядно демонстрирует мощь инкапсуляции: чтобы добраться до внутренних деталей, нужно явно пройти через каждую "границу". Это делает код более предсказуемым и защищает компоненты от случайных изменений.
Инкапсуляция от CSS
Стили, определённые на основной странице, не влияют на элементы внутри теневого DOM.
Элемент <span> внутри теневого дерева не получит эти стили. Это решает огромную проблему случайных пересечений и конфликтов CSS.
Применение стилей внутри теневого DOM
Стили, определённые внутри теневого дерева, в свою очередь, не влияют на основную страницу. Есть два основных способа их добавления.
1. Конструируемые таблицы стилей (Constructable Stylesheets)
Этот метод позволяет создавать объект CSSStyleSheet в JavaScript и применять его к одному или нескольким теневым деревьям. Это эффективно, если у вас есть общие стили для множества компонентов.
2. Добавление элемента <style>
Простой и декларативный способ — поместить тег <style> прямо внутрь теневого дерева (часто внутри <template>).
Теневой DOM и пользовательские элементы: идеальное сочетание
Вся мощь теневого DOM раскрывается при создании пользовательских элементов (Custom Elements). Без инкапсуляции они были бы невероятно хрупкими.
Пользовательский элемент — это класс, наследующий HTMLElement. Как правило, сам элемент выступает в роли теневого хоста, а вся его внутренняя структура создаётся внутри теневого дерева.
Вот пример простого компонента <filled-circle>:
Теперь мы можем использовать его в HTML как обычный тег, не беспокоясь о его внутреннем устройстве:
Каждый из этих компонентов будет полностью инкапсулирован и защищён от влияния внешней страницы.
Полезно? Подпишись.
Удачи 🚀
Всем привет! Ещё один интересный вопрос с нашего Телеграм-канала про SQL и базы данных. Спасибо, что делитесь вопросами с собеседований!