safety4d


# Safety4D Framework para Controle de Regras de Acesso de Usuários inspirado no conceito RBAC. ## Instalação Basta registrar no Library Path do seu Delphi o caminho da pasta SRC da Biblioteca ou utilizar o Boss (https://github.com/HashLoad/boss) para facilitar ainda mais, executando o comando ``` boss install https://github.com/bittencourtthulio/safety4d ``` ## Primeiros Passos - Tutorial Para utilizar o Safety4D você deve adicionar a uses ``` Safety4D ``` ### Como funciona O Safety4D foi baseado no conceito de RBAC ( role-based access control) https://pt.wikipedia.org/wiki/Controle_de_acesso_baseado_em_fun%C3%A7%C3%B5es Ele se baseia em uma estrutura JSON de configuração para definição das permissões, inspirada na estrutura utilizada pelo Windows Azure. https://docs.microsoft.com/pt-br/azure/role-based-access-control/overview Abaixo o exemplo de um arquivo de configuração ```JSON { "resources": { "safety4d": { "users": { "actions": { "read": { "description": "read-only", "errormsg": "not permit" }, "write": { "description": "read-write", "errormsg": "not write data" }, "delete": { "description": "delete-data", "errormsg": "not delete data" }, "view": { "description": "view data", "errormsg": "not view data" } } } } }, "groupPermission": { "{4D62E4C3-C73D-488A-8518-03A9545B5611}": { "key": "Gerente", "description": "Permissoes completa de gestao do Sistema", "Actions": [ "users.write" ], "NotActions": [ "*" ] }, "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}": { "key": "Comercial", "description": "Permissoes de Recursos Comerciais", "Actions": [ "*" ], "NotActions": [ "users.delete", "users.write" ] } }, "userKeys": { "{34C940ED-50E7-4CE3-B701-03CF1E15F28B}": { "description": "Fulano de Tal", "permissionGroups": [ "{4D62E4C3-C73D-488A-8518-03A9545B5611}" ] }, "{96B4C46F-0EBB-443B-B309-09C81844406E}": { "description": "Beltrano", "permissionGroups": [ "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}" ] } } } ``` ## Explicando a Estrutura Abaixo vou detalhar cada bloco do JSON acima explicando o objetivo e a aplicação de cada recurso. ### Resources Neste bloco você vai cadastrar a sua aplicação, os recursos dela e as ações que você deseja validar. ```JSON "resources": { "safety4d": { "users": { "actions": { "read": { "description": "read-only", "errormsg": "not permit" }, "write": { "description": "read-write", "errormsg": "not write data" }, "delete": { "description": "delete-data", "errormsg": "not delete data" }, "view": { "description": "view data", "errormsg": "not view data" } } } } }, ``` No exemplo acima, estamos cadastrando a aplicação chamada safety4d, o recursos chamados users e as ações disponíveis neste recurso read, write, delete, view . Você pode cadastrar quantas ações desejar para um recurso. ### Group Permission Neste bloco você cria os grupos de permissão que serão atribuidos aos usuários, definindo quais recursos e actions podem e não podem ser acessados pelos usuários do grupo. No bloco Actions você define todos os recursos e actions que os participantes do grupo terão acesso, e no bloco NotActions você define todos os recursos e actions que estarão bloqueados para os participantes do grupo. Utilizando o caracter "*" no bloco Actions você está liberando o acesso a todos os recursos exceto aqueles que estiverem especificados na sessão NotActions. Utilizando o caracter "*" no bloco NotActions você está bloqueando o acesso a todos os recursos exceto aqueles que estiverem especificados na sessão Actions. ```JSON "groupPermission": { "{4D62E4C3-C73D-488A-8518-03A9545B5611}": { "key": "Gerente", "description": "Permissoes completa de gestao do Sistema", "Actions": [ "users.write" ], "NotActions": [ "*" ] }, "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}": { "key": "Comercial", "description": "Permissoes de Recursos Comerciais", "Actions": [ "*" ], "NotActions": [ "users.delete", "users.write" ] } }, ``` No exemplo acima cadastramos 2 grupos de permissões distindos, no primeiro grupo Gerente definimos em Actions que os participantes desse grupo só podem acessar o recurso users executando a ação write e o caracter "*" na sessão NotActions sinaliza que todas as demais funções estão bloqueadas. No segundo grupo todas as Actions estão liberadas, exceto as que estão descritas no bloco NotActions. ### User Keys Neste bloco você cadastra as chaves referentes aos usuários do sistema, atribuindo a eles as keys dos Grupos de Permissões que ele participa. ```JSON "userKeys": { "{34C940ED-50E7-4CE3-B701-03CF1E15F28B}": { "description": "Fulano de Tal", "permissionGroups": [ "{4D62E4C3-C73D-488A-8518-03A9545B5611}" ] }, "{96B4C46F-0EBB-443B-B309-09C81844406E}": { "description": "Beltrano", "permissionGroups": [ "{C188D1AB-EC28-4380-96E0-D1B13A29A8B3}" ] } } ``` ## Utilizando no Delphi Você pode utilizar os recursos do proprio componente para criar seu arquivo de configuração ou criar manualmente e carrega-lo no componentes. ### Carregando um JSON já pronto ```delphi var aJson : TJsonObject; begin aJson := TJSONObject.ParseJSONValue('SEU JSON') as TJsonObject; try TSafety4D.New.LoadConfig(aJson); finally aJson.Free; end; ``` Uma vez estando com as configurações do arquivo carregadas no componente TSafety4D, você pode utilizar os recursos de validação. ### Validando o acesso a um recursos ```delphi TSafety4D.New .Validation .userKey('CHAVE DO USERKEY') .application('APPLICATION DO RECURSO') .resource('NOME DO RECURSOS') .action('ACTION A SER EXECUTADA') .validate; ``` Abaixo o exemplo utilizando os dados do arquivo de configuração que mostramos acima, verificando se um usuário especifico possuí a permissão para escrever no recurso de users. ```delphi TSafety4D.New .Validation .userKey('{34C940ED-50E7-4CE3-B701-03CF1E15F28B}') .application('safety4d') .resource('users') .action('write') .validate; ``` O Safety4D trabalha com uma instancia Singleton, ou seja, a mesma instancia é compartilhada em toda a aplicação, com isso algumas configurações você pode deixar por default como por exemplo userKey e application que provavelmente não irão mudar em uma sessão de usuário durante o uso. Sendo assim você pode por exemplo na instancia principal da sua aplicação já deixar esses valores setados. ```delphi TSafety4D.New .Validation .userKey('{34C940ED-50E7-4CE3-B701-03CF1E15F28B}') .application('safety4d'); ``` E durante o uso nas demais telas você não precisa mais passar essas informações para realizar a validação de um recurso. ```delphi TSafety4D.New .Validation .resource('users') .action('write') .validate; ``` ### Exceptions A função validade retorna um boolean sinalizando se o acesso é permitido ou não, porém você pode tratar a permissão fazendo com que o TSafety4D dispare uma excessão com a mensagem do que falhou na validação, não necessitando assim de estrutura condicional para validar o acesso. ```delphi TSafety4D.New .configurations .exceptions(True) .&end .Validation .userKey('{34C940ED-50E7-4CE3-B701-03CF1E15F28B}') .application('safety4d') .resource('users') .action('write') .validate; ``` ## Definindo as Configurações pelo Sistema Você pode criar o arquivo de configuração manualmente e carrega-lo no componente ou utilizar o proprio componente para definir as configurações. ```delphi TSafety4D .New .resources .registerResources .resourcesGroupName .add('newapplication') .providerName .add('users') .actions .add('read') .description('read-only') .errormsg('not permit') .&end .add('write') .description('read-write') .errormsg('not write data') .&end .add('delete') .description('delete-data') .errormsg('not delete data') .&end .add('view') .description('view data') .errormsg('not view data') .&end .&end .&end .&end .&end .&end .groupPermission .groupRegister .add('Operador') .description('Funções de Operador do Sistema') .actions .add('users.view') .&end .notActions .add('*') .&end .&end .&end .userKey .registerUserKey .add('Fulano de Tal') .addPermission('{96B4C46F-0EBB-443B-B309-09C81844406E}') .&end .&end .&end; ``` ### Transformando as configuração do Componente em Json Utilizando o código abaixo você carrega toda a configuração do componentes para um TJsonObject. ```delphi var aJsonSafety4D : TJsonObject; begin aJsonSafety4D := TJSONObject.Create; try TSafety4D.New.getConfig(aJsonSafety4D); Memo1.Lines.Clear; Memo1.Lines.Add(aJsonSafety4D.Format); finally aJsonSafety4D.Free; end; ``` ### Salvando a configuração em um Arquivo no Disco Você pode utilizar o recursos abaixo para salvar as configurações diretamente no disco. ```delphi TSafety4D.New.SaveToStorage(); ``` ## Dica Crie a estrutura e salve ela no seu banco de dados em um campo de texto e carregue toda vez que abrir a aplicação ou tiver alguma mudança nas configurações para o componente.