Saltar para o conteúdo principal
Versão: v20 R4

Privileges

Protecting data while allowing fast and easy access to authorized users is a major challenge for web applications. The ORDA security architecture is implemented at the heart of your datastore and allows you to define specific privileges to all user sessions for the various resources in your project (datastore, dataclasses, functions, etc.).

Visão Geral

The ORDA security architecture is based upon the concepts of privileges, permission actions (read, create, etc.), and resources.

When users get logged, their session is automatically loaded with associated privilege(s). Privileges are assigned to the session using the session.setPrivileges() function.

Every user request sent within the session is evaluated against privileges defined in the project's roles.json file.

If a user attempts to execute an action and does not have the appropriate access rights, a privilege error is generated or, in the case of missing Read permission on attributes, they are not sent.

esquema

Resources

You can assign specific permission actions to the following exposed resources in your project:

  • o armazenamento de dados
  • uma classe de dados
  • um atributo (inclusive calculado e aliases)
  • uma função de classe de modelo de dados

A permission action defined at a given level is inherited by default at lower levels, but several permissions can be set:

  • A permission action defined at the datastore level is automatically assigned to all dataclasses.
  • Uma ação de permissão definida ao nível da classe de dados substitui a definição do armazenamento de dados (se existir). By default, all attributes of the dataclass inherit from the dataclass permission(s).
  • Unlike dataclass permissions, a permission action defined at the attribute level does not override the parent dataclass permission(s), but is added to. For example, if you assigned the "general" privilege to a dataclass and the "detail" privilege to an attribute of the dataclass, both "general" and "detail" privileges must be set to the session to access the attribute.

Acções de autorização

As ações disponíveis estão relacionadas com o recurso alvo.

Acçõesarmazém de dadosdataclassatributofunção de modelo de dados
createCriar entidade em qualquer classe de dadosCriar entidade nesta classe de dadosCreate an entity with a value different from default value allowed for this attribute (ignored for alias attributes).n/a
readLer atributos em qualquer dataclassLer atributos nesta classe de dadosLeia o conteúdo desse atributon/a
updateAtualizar atributos em qualquer classe de dados.Atualiza os atributos nesta classe de dados.Atualiza o conteúdo deste atributo (ignorado para atributos alias).n/a
dropEliminar dados em qualquer classe de dados.Eliminar dados nesta classe de dados.Delete a not null value for this attribute (except for alias and computed attribute).n/a
executeExecute any function on the project (datastore, dataclass, entity selection, entity)Executa qualquer função na classe de dados. Dataclass functions, entity functions, and entity selection functions are handled as dataclass functionsn/aExecutar esta função
describeTodas as classes de dados estão disponíveis na /rest/$catalog APIEsta dataclass está disponível na API /rest/$catalogEsse atributo está disponível na API /rest/$catalog.Esta função de classe de dados está disponível na API /rest/$catalog
promoten/an/an/aAssocia um determinado privilégio durante a execução da função. The privilege is temporary added to the session and removed at the end of the function execution. By security, only the process executing the function is added the privilege, not the whole session.

Notas:

  • An alias can be read as soon as the session privileges allow the access to the alias itself, even if the session privileges do no allow the access to the attributes resolving the alias.
  • A computed attribute can be accessed even if there are no permissions on the attributes upon which it is built.
  • Default values: in the current implementation, only Null is available as default value.

A definição das permissões deve ser coerente, nomeadamente:

  • update and drop permissions also need read permission (but create does not need it)
  • promote permission also need describe permission.

Privilégios e roles

A privilege is the technical ability to run actions on resources, while a role is a privilege pusblished to be used by an administrator. Basically, a role gathers several privileges to define a business user profile. For example, "manageInvoices" could be a privilege while "secretary" could be a role (which includes "manageInvoices" and other privileges).

A privilege or a role can be associated to several "action + resource" combinations. Podem ser associados vários privilégios a uma ação. Um privilégio pode incluir outros privilégios.

  • You create privileges and/or roles in the roles.json file (see below). You configure their scope by assigning them to permission action(s) applied to resource(s).

  • You allow privileges and/or roles to every user session using the .setPrivileges() function of the Session class.

Exemplo

Para permitir uma função em uma sessão:


exposed Function authenticate($identifier : Text; $password : Text)->$result : Text

var $user : cs. UsersEntity

Session.clearPrivileges()

$result:="Your are authenticated as Guest"

$user:=ds. Users.query("identifier = :1"; $identifier).first()

If ($user#Null)
If (Verify password hash($password; $user.password))
Session.setPrivileges(New object("roles"; $user.role))
$result:="Your are authenticated as "+$user.role
End if
End if


ficheiro roles.json

The roles.json file describes the whole security settings for the project.

nota

In a context other than Qodly (cloud), you have to create this file at the following location: <project folder>/Project/Sources/. Ver a seção Arquitetura.

A sintaxe do ficheiro roles.json é a seguinte:

Nome da propriedadeTipoObrigatórioDescrição
privilegesColeção de objectos privilegeXLista de privilégios definidos
[].privilegeStringNome do privilégio
[].includesColeção de stringsLista de nomes de privilégios incluídos
rolesColeção de objetos roleLista de roles definidos
[].roleStringNome da role
[].privilegesColeção de stringsLista de nomes de privilégios incluídos
permissionsObjectXLista de acções permitidas
allowedColeção de objectos permissionLista de permissões permitidas
[].applyToStringXTargeted resource name
[].typeStringXResource type: "datastore", "dataclass", "attribute", "method"
[].readColeção de stringsLista de privilégios
[].createColeção de stringsLista de privilégios
[].updateColeção de stringsLista de privilégios
[].dropColeção de stringsLista de privilégios
[].describeColeção de stringsLista de privilégios
[].executeColeção de stringsLista de privilégios
[].promoteColeção de stringsLista de privilégios
Lembrete
  • O nome do privilégio "WebAdmin" está reservado à aplicação. Não se recomenda a utilização deste nome para privilégios personalizados.
  • privileges and roles names are case insensitive.

ficheiro Roles_Errors.json

O arquivo roles.json é analisado por 4D na inicialização. You need to restart the application if you want modifications in this file to be taken into account.

In case of error(s) when parsing the roles.json file, 4D loads the project but disables the global access protection - this allows the developer to access the files and to fix the error. An error file named Roles_Errors.json is generated in the Logs folder of the project and describes the error line(s). This file is automatically deleted when the roles.json file no longer contains error(s).

It is recommended to check at startup if a Roles_Errors.json file exists in the Logs folder, which means that there was a parsing error and that accesses will not limited. Pode escrever, por exemplo:

/Sources/DatabaseMethods/onStartup.4dm
If (Not(File("/LOGS/"+"Roles_Errors.json").exists))

Else // you can prevent the project to open
ALERT("The roles.json file is malformed or contains inconsistencies, the application will quit.")
QUIT 4D
End if

Inicialização de privilégios para implantação

By default, if no specific parameters are defined in the roles.json file, accesses are not limited. This configuration allows you to develop the application without having to worry about accesses.

However, when the application is about to be deployed, a good practice is to lock all privileges and then, to configure the file to only open controlled parts to authorized sessions. To lock all privileges on all resources, put the following roles.json file in your project folder (it includes examples of methods):

/Project/Sources/roles.json
{
"privileges": [
{
"privilege": "none",
"includes": []
}
],

"roles": [],

"permissions": {
"allowed": [{
"applyTo": "ds",
"type": "datastore",
"read": [
"none"
],
"create": [
"none"
],
"update": [
"none"
],
"drop": [
"none"
],
"execute": [
"none"
],
"describe": [
"none"
],
"promote": [
"none"
]
},
{
"applyTo": "ds.loginAs",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.hasPrivilege",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.clearPrivileges",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.isGuest",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.getPrivileges",
"type": "method",
"execute": [
"guest"
]
},
{
"applyTo": "ds.setAllPrivileges",
"type": "method",
"execute": [
"guest"
]
}

]
}
}