воскресенье, 7 января 2018 г.

Архитектурные принципы

  Архитектурные принципы представляют собой фундаментальные «аксиомы» (или правила), которые используются в качестве «отправных точек» для принятия архитектурных решений. В свою очередь, архитектурные принципы являются подмножеством более общего понятия ИТ-принципов, которые определяют основные аспекты всей деятельности, связанной с применением информационных технологий.

В состав набора принципов могут входить обоснования для формирования системы требований или критериев оценки тех или иных решений. Например, такой принцип, как «минимизация числа поставщиков программного обеспечения», может быть в дальнейшем конкретизирован в зависимости от особенностей компании, как требование «единой СУБД для всех критичных для бизнеса приложений» или же как «использование той же СУБД, что и уже применяемая».

Принципы являются взаимозависимыми и должны применяться целостно. Обычно число принципов для реализации решения не превышает 7-8 (а лучше 4-5), это необходимо, чтобы не ограничивать гибкость архитектуры или чтобы избежать чисто формального определения принципов, которые не приносят пользы на практике.

Использование принципов при работе над архитектурой доказало свою эффективность. В следующих постах будут приведены примеры архитектурных принципов, а в этой статье начнём с принципов безопасности:

Принцип наименьших полномочий

Формулировка
Пользователи и потребители ресурсов должны иметь минимальные полномочия необходимые для выполнения действий (работы).
Основная причина
Когда пользователю и потребителю ресурса предоставлены большие полномочия, чем требуется, то риски в части безопасности возрастают.
Следствия/выводы
  • Пользователям должен быть предоставлен доступ к функциям и данным на основе их ролей в системе;
  • Должен предоставляться только минимально необходимый для выполнения функций доступ.

Также смотрите:

четверг, 26 января 2017 г.

Резервное копирование Skype-переписки для Windows

Давно задумывался об сохранении всей истории переписок в Skype при переустановке ОС или при переходе на новый ноутбук.
На этот счёт есть полезная статья на сайте поддержки Skype - Can I back up my chat history and transfer it from one computer to another?. Но выполнять данные действия вручную для меня не удобно, поэтому сделал скрипт позволяющий автоматизировать данный процесс и сохранять переписку в файловое хранилище (в моём случае Dropbox).
Нужно запустить cmd от Администратора:
REM Script creation echo REM Article https://support.skype.com/en/faq/FA392/how-do-i-manage-my-conversation-history-in-skype-for-windows-desktop > BackupSkype.cmd echo title SkypeBackup >> BackupSkype.cmd echo SET SKYPE_ACCOUNT_NAME=stanislav.devyatov>>BackupSkype.cmd echo SET SKYPE_BACKUP_FOLDER=C:\Users\Stanislav\Dropbox\Backup>>BackupSkype.cmd echo SET ARCH_7ZIP_HOME="C:\Program Files (x86)\7-Zip">>BackupSkype.cmd echo taskkill /f /IM skype.exe >> BackupSkype.cmd echo sleep 10 >> BackupSkype.cmd REM Create new file REM echo %7Zip_HOME%\7z.exe a %SKYPE_BACKUP_FOLDER%\skypeBackup_%date%.zip %appdata%\Skype\%SKYPE_ACCOUNT_NAME% -mx9>>BackupSkype.cmd echo %ARCH_7ZIP_HOME%\7z.exe a %SKYPE_BACKUP_FOLDER%\skypeData.zip %appdata%\Skype\%SKYPE_ACCOUNT_NAME% -aoa>>BackupSkype.cmd echo start skype >> BackupSkype.cmd REM Copy script move /Y BackupSkype.cmd %appdata%\Skype\ REM Create task SchTasks /Create /F /SC DAILY /TN MySkypeBackup /TR %appdata%\Skype\BackupSkype.cmd /RL HIGHEST /ST 12:00
Требуется установить 7-Zip и изменить значение полей выделенных желтым.

среда, 16 марта 2016 г.

Ошибка при создании домена по умолчанию в JDeveloper 12.2.1 на платформе Windows 10

Ошибка:
 wlst >   
 wlst > Initializing WebLogic Scripting Tool (WLST) ...  
 wlst >   
 wlst > Welcome to WebLogic Server Administration Scripting Shell  
 wlst >   
 wlst > Type help() for help on available commands  
 wlst >   
 wlst > Failed to get environment, environ will be empty: (0, u'Failed to execute command ([\'sh\', \'-c\', \'env\']): java.io.IOException: Cannot run program "sh": CreateProcess error=2, \u041D\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044F \u043D\u0430\u0439\u0442\u0438 \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u044B\u0439 \u0444\u0430\u0439\u043B')  
 wlst > Error: ADRS_DOMAIN_PASSWORD environment variable not set.  
 wlst >   
 wlst >   
 wlst > Exiting WebLogic Scripting Tool.  
 wlst >   

Варианты решения:
1. Изменить архиве
%JDEVELOPER_HOME%/wlserver/common/wlst/modules/jython-modules.jar следующий файл \Lib\javashell.py (добавленное выделено красным):
   ...
   os = str(os or sys.registry.getProperty( "python.os" ) or \  
         System.getProperty( "os.name" ))  
   _osTypeMap = (  
     ( "nt", ( 'nt', 'Windows NT', 'Windows NT 4.0', 'WindowsNT',  
          'Windows 2000', 'Windows 2003', 'Windows XP', 'Windows CE',  
          'Windows Vista', 'Windows Server 2008', 'Windows 7', 'Windows 8',   
          'Windows 10', 'Windows Server 2012' )),  
     ( "dos", ( 'dos', 'Windows 95', 'Windows 98', 'Windows ME' )),  
     ( "mac", ( 'mac', 'MacOS', 'Darwin' )),  
     ( "None", ( 'None', )),  
     )
   ...  

2. Открыть сервисный запрос (SR) в поддержку и получить официальный патч.

среда, 30 декабря 2015 г.

Пользовательские задачи Oracle BPM 12c: роли и подразделения пользователей

Участником задачи могут быть:
  • пользователь (user);
  • группа пользователей (group);
  • роль пользователей (app.role), в контексте Oracle BPM.
Взаимосвязь между участниками указана ниже:

Орг.единицы (Organization Unit) определяют структуру организации, например:

Важно отметить, что орг.единицы логически связанны только с ролями пользователей (т.е. не для группы пользователей и тем более не для пользователя).

Рассмотрим на примере как работает механизм орг.единиц:

В соответствии со схемой выше, в организации есть 3 бухгалтера по одному в каждом отделении и аналогично 3 инженера в каждом отделении.
Создадим две роли "Бухгалтер" и "Инженер" и три орг.подразделения и добавим в них соответствующих сотрудников. Таким образом получается:
Роль
Пользователь
Организационное подразделение
Бухгалтер
Иванова
Западносибирское отд.
Сидирова
Уральское отделение
Кузнецова
Дальневосточное отд.
Инженер
Петрова
Западносибирское отд.
Алексеева
Уральское отделение
Борисова
Дальневосточное отд.

Создадим простейший BPMN-процесс с одной задачей:

Но данная задача должна назначаться на роль "Бухгалтер" уральского подразделения, для этого добавляем перед назначением задачи добавим script-активность, в которой укажем необходимое орг.подразделение (Process / Predefined Variables / Organization Unit):
Если бы мы не указали орг.подразделение, то задача назначилась на всех участников роли "Бухгалтер", т.е. доступ был бы у 3-х сотредников. 
Так как мы указали орг.подразделение, то задача назначится на того сотрудника роли "Бухгалтер", который входит в указанное подразделение, т.е. Сидорову.

Данная функциональность позволяет сильно сократить количество ролей (без неё потребовалось бы 6 ролей вместо 2).

воскресенье, 8 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: пример реализации ограничения перечня пользователей для операции "Делегирование"

По умолчанию задачу в Oracle BPM можно переназначить или делегировать на любого пользователя, роль и группу. Но можно ограничить этот перечень создав класс в BPM-проекте (в терминах JDeveloper), который реализует интерфейс oracle.bpel.services.workflow.task.IRestrictedAssignmentCallback.

Рассмотрим пример в котором нужно ограничить перечень пользователей для операции "Делегирование" следующим образом:
  • Если исполнителем задачи является группа или роль, то делегировать можно только пользователям из состава этой группы или роли;
  • Если исполнителем задачи является пользователь, то делегировать нельзя (пустой перечень доступных для делегирования пользователей).
Пример кода:
 import java.util.ArrayList;  
 import java.util.Collections;  
 import java.util.List;  
 import java.util.Map;  
   
 import oracle.bpel.services.workflow.IWorkflowConstants;  
 import oracle.bpel.services.workflow.task.IRestrictedAssignees;  
 import oracle.bpel.services.workflow.task.IRestrictedAssignmentCallback;  
 import oracle.bpel.services.workflow.task.impl.RestrictedAssignees;  
 import oracle.bpel.services.workflow.task.impl.TaskAssignee;  
 import oracle.bpel.services.workflow.task.model.Task;  
   
 import oracle.tip.pc.services.common.ServiceFactory;  
 import oracle.tip.pc.services.identity.BPMAppRole;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
 import oracle.tip.pc.services.identity.BPMGroup;  
 import oracle.tip.pc.services.identity.BPMIdentityService;  
 import oracle.tip.pc.services.identity.BPMUser;  
   
 import oracle.bpel.services.workflow.task.model.IdentityType;  
   
 public class RestrictedAssignmentCallbackImpl implements IRestrictedAssignmentCallback {  
   
   public IRestrictedAssignees getPermittedAssignees(Task task, Map map, String currentUser, String identityContext,  
                            String operation) {  
     List assignees = new ArrayList();  
     if (operation.equals(IRestrictedAssignmentCallback.OperationType.REASSIGN.toString())) {  
       //TODO реализовать логику для операции "Переназначение"  
     } else if (operation.equals(IRestrictedAssignmentCallback.OperationType.DELEGATE.toString())) {  
       try {  
         BPMIdentityService idenService = getIdentityServiceInstance(identityContext);  
         List<IdentityType> assigneesList = task.getSystemAttributes().getAssignees();  
         for (IdentityType assignee : assigneesList) {  
           if (IWorkflowConstants.IDENTITY_TYPE_GROUP.equals(assignee.getType())) {  
             List<BPMUser> usersInGroup =  
               idenService.getParticipantsToGroup(assignee.getDisplayName(), true);  
             for (BPMUser user : usersInGroup) {  
               assignees.add(new TaskAssignee(user.getName(), IWorkflowConstants.IDENTITY_TYPE_USER));  
             }  
           } else if (IWorkflowConstants.IDENTITY_TYPE_APPLICATION_ROLE.equals(assignee.getType())) {  
             List<BPMUser> usersInGroup =  
               idenService.getParticipantsToAppRole(assignee.getDisplayName(),  
                                  task.getApplicationContext(), false);  
             for (BPMUser user : usersInGroup) {  
               assignees.add(new TaskAssignee(user.getName(), IWorkflowConstants.IDENTITY_TYPE_USER));  
             }  
           } else if (IWorkflowConstants.IDENTITY_TYPE_USER.equals(assignee.getType())) {  
             // Пустой список  
             return new RestrictedAssignees(new ArrayList(), true);  
           }  
         }  
   
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     }   
   
     if (!assignees.isEmpty()) {  
       return new RestrictedAssignees(assignees, true);  
     }  
   
     return null;  
   }  
   
   public List<IRestrictedAssignmentCallback.OperationType> getRestrictedOperations(Task task, Map map,  
                                            String currentUser,  
                                            String identityContext) {  
     return Collections.emptyList();  
   }  
   
   private BPMAuthorizationService getAuthorizationService(String realmName) {  
     return ServiceFactory.getAuthorizationServiceInstance(realmName);  
   }  
   
   private BPMIdentityService getIdentityServiceInstance(String realmName) {  
     return ServiceFactory.getIdentityServiceInstance(realmName);  
   }  
 }  
   

суббота, 7 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: Custom Escalation Java Function

Custom Escalation Java Function указывается в конфигурации задачи для указания по какой логике будет выполняться эскалация для пользователей и групп (для ролей не используется!).

Custom Escalation Java Function рассмотрим на примере:
 package oracle.bpel.services.workflow.assignment.dynamic;  
   
 import java.util.List;  
 import java.util.Map;  
   
 import oracle.bpel.services.workflow.task.model.Task;  
 import oracle.bpel.services.workflow.assignment.dynamic.DynamicAssignmentException;  
   
 import oracle.tip.pc.services.common.ServiceFactory;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
   
 import oracle.tip.pc.services.identity.BPMAppRole;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
 import oracle.tip.pc.services.identity.BPMGroup;  
 import oracle.tip.pc.services.identity.BPMIdentityService;  
 import oracle.tip.pc.services.identity.BPMUser;  
 /*  
  * Обеспечивает эскалацию на владельца задачи.  
  */  
 public class OwnerEscalation implements IDynamicTaskEscalationFunction {  
   public String defaultUser;  
   
   @Override  
   public String getTaskEscalationUser(Task task) throws DynamicAssignmentException {  
     String ownerRole = task.getOwnerRole();  
     String ownerGroup = task.getOwnerGroup();  
     String ownerUser = task.getOwnerUser();  
     if (ownerRole != null) {  
       try {  
         BPMAuthorizationService idenService = ServiceFactory.getIdentityServiceInstance();  
         List<BPMUser> usersInRole =  
           idenService.getParticipantsToAppRole(ownerRole, task.getApplicationContext(), false);  
         if (usersInRole.size() > 0) {  
           // Берём первого пользователя  
           return usersInRole.get(0).getName();  
         }  
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     } else if (ownerGroup != null) {  
       try {  
         BPMAuthorizationService idenService = ServiceFactory.getIdentityServiceInstance();  
         List<BPMUser> usersInGroup = idenService.getParticipantsToGroup(ownerGroup, true);  
         if (usersInGroup.size() > 0) {  
           // Берём первого пользователя  
           return usersInGroup.get(0).getName();  
         }  
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     } else if (ownerUser != null) {  
       return ownerUser;  
     }  
     return defaultUser;  
   }  
   
   @Override  
   public String getTaskEscalationUser(String string) throws DynamicAssignmentException {  
     return defaultUser;  
   }  
   
   @Override  
   public void setInitParams(Map map) throws DynamicAssignmentException {  
     // Добавляем параметр указывающий на какого пользователя проводить эскалацию,   
     // если владелец задачи (Owner) не указан  
     defaultUser=(String)map.get("DEFAULT_USER");  
   }  
   
   @Override  
   public String getFunctionName() {  
     return "OWNER_ESCALATION";  
   }  
   
   @Override  
   public String getDescription() {  
     return "Escalation to task owner";  
   }  
 }  
   
Логика данного примера:
Если у задачи определён владелец (Owner), то эскалация будет выполняться на владельца. Иначе, на пользователя указанного в конфигурации как DEFAULT_USER

Важно:

  • Класс должен быть в пакете oracle.bpel.services.workflow.assignment.dynamic.

Установка:

  1. Собрать JAR содержащий класс и положить его в директорию $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1
  2. Запустить ant в директории $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1 (вероятно потребуется проинициализировать переменные окружения)
  3. Перезагрузить soa-сервер для того, чтобы новый класс был доступен серверу (был в classpath).
  4. Зарегистрировать Task Escalation Function:
    1. Войти в EM (Enterprise Manager Fusion Middleware Control)
    2. Перейти в soa-infra -> SOA Administration -> Workflow Properties
    3. Перейти на закладку Task и добавить наш класс (Add function) следующим образом:
Альтернативный вариант: вместо указанных действий в п.1-2 можно положить скомпилированный класс в директорию $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1\classes

вторник, 3 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: новая функциональность таймеров

После авторизации в Oracle BPM Workspace 12c выбрав экземпляр любой задачи вы обнаружите, что у задач появились два новых действия:
  • Начать работу (Start Task)
  • Закончить работу (Stop Task)
Функциональность данных действий работает следующим образом:
После выполнения "Начать работу" включается таймер, а после выполнения "Закончить работу" таймер выключается и сохраняется длительность включённого таймера с нарастающим итогом

Особенности

  • Функциональность "Начать работу" / "Закончить работу" не генерируют событий (EDN), поэтому значения можно узнать через API или в следующем (по времени) генерируемом событии.
  • Если задача назначена на группу/роль, то выполнение "Начать работу" приводит так же к выполнению "Взять в работу".
  • Если пользователь выполнил "Начать работу" и затем исполнил/завершил задачу (т.е. не была выполнена операция "Закончить работу"), то значение таймера длительности будет 0. 
  • Таймер никак не связан с пользователями выполняющими действия. Последовательный пример: 
    1. назначается задача на первого пользователя
    2. первый пользователь выполняет "Начать работу"
    3. первый пользователь переназначает на второго пользователя
    4. второй пользователь выполняет "Закончить работу" и исполняет/завершает задача
    В итоге: нет информации сколько времени с задачей работал первый пользователь, а сколько второй. Есть только информация сколько времени прошло с включения таймера (действия "Начать работу") до выключения таймера (действия "Закончить работу").

Недостатки

  • Данная функциональность не документирована (ни в пользовательской документации, ни в Oracle Fusion Middleware Workflow Services Java API Reference for Oracle SOA Suite).
  • Следствие первого пункта - доступна только из Oracle BPM Workspace 12c (как следствие, не доступна, если вы не используете его).
  • Следствие первого пункта - данная функциональность может быть изменена вендором (пока не будет внесена в публичную документацию). 

суббота, 31 октября 2015 г.

Пользовательские задачи Oracle BPM 12c: эскалация

Под эскалацией в Oracle BPM 12c (и в 11g) подразумевается автоматическое переназначение исполнителя задачи на другую роль, группу или пользователя (обычно более высокого по иерархии).

Эскалация может производиться:
  • автоматически по истечению указанного времени в конфигурации задачи
  • пользователем выполнившим действие «Эскалировать» (Escalate), которое может быть доступно:
    • Исполнителю задачи (Assignee)
    • Владельцу задачи (Owner)
    • Администратору (Admin)

Особенности:

  • В зависимости от того на ком находится задача на момент эскалации:
    • Если это группа или пользователь, то отрабатывает указанная custom escalation java function (если функция не указана, то задача завершится будет ошибкой)
    • Если это роль, то выполняется эскалация на указанный в роли Escalation Path (может быть роль, группа, пользователь).
       
    • Последующие эскалации:
      • Если в Escalation Path указана роль, то последующая эскалация будет выполнятся на Escalation Path данной роли
      • Если в Escalation Path указан пользователь или группа, то отрабатывает указанная custom escalation java function (если функция не указана, то задача завершится будет ошибкой).
  • Для каждой задачи можно задать глубину автоматической эскалации, т.е. кол-во раз которое будет выполнятся эскалация. По истечению указанного количества задача становится просроченной (expired).

четверг, 4 июня 2015 г.

Декодирование xsd:base64Binary в xsd:string

Цель:
При использовании JMS Adapter для получения текстового сообщения в формате XML, для которого XSD не известна, используется опция "Native format translation is not required (Schema is Opaque)". В этом случае входящее сообщение будет содержать элемент типа xsd:base64Binary, содержащий закодированное в base64 полученное сообщение.
Решение:
Т.к. в Oracle SOA Suite 11g отсутствует XSLT или XPATH-функции, позволяющая декодировать base64, поэтому можно использовать активность "Java Embedding" для решения данной задачи.
Итак, в BPEL-процессе есть две переменные:
 <!-- входная переменная из JMS Adapter -->
 <variable name="encoded_Input" messageType="ns1:Consume_Message_msg"/>  
 <!-- переменная в которую декодируем base64 -->
 <variable name="decoded_Input" type="xsd:string"/>
Добавляем в BPEL-процесс активность "Java Embedding" содержащую следующий код:
 try {      
     oracle.xml.parser.v2.XMLElement input = (oracle.xml.parser.v2.XMLElement) getVariableData("encoded_Input", "opaque");
     String input_str = input.getTextContent();   
     oracle.soa.common.util.Base64Decoder decoder = new oracle.soa.common.util.Base64Decoder();        
     String decoded = null;       
     decoded = decoder.decode(input_str);   
     setVariableData("decoded_Input", decoded);      
 } catch (Exception e) {  
     addAuditTrailEntry("EXCEPTION OCCURRED: " + e.toString());  
 }  

Альтернативный вариант - создание собственной XSLT или XPATH-функции для декодирования base64.

четверг, 16 апреля 2015 г.

Освоение Oracle BPM

Требуется:
Выполнить простейший tutorial с Oracle Technology NetworkДалее выполнить tutorial по одной из следующих книг:
  • Getting Started with Oracle BPM Suite 11gR1
  • Oracle BPM Suite 11g Developer's Cookbook
Изучить "продвинутые" аспекты по книге: 
  • Oracle BPM Suite 11g Advanced BPMN Topics
Полезные ссылки: