O primeiro passo para se criar uma aplicação web dentro da Pluga é incluir os dados básicos de descrição (nome, links para o site, URI base da API, descrição geral da aplicação, etc) e o método de autenticação (OAuth2, Basic Auth, Pass Through Querystring, etc).
E para explicar como fazê-la, nada melhor do que um exemplo real para ilustrar. Abaixo temos a configuração da aplicação Asana.
{% code title="lib/app.json" %}
{
"app_id": "asana",
"name": "Asana",
"color": "#89324F",
"description": {
"pt_BR": "Asana é a plataforma de gerenciamento do trabalho que as equipe usam para permanecer focadas nas metas, projetos e tarefas diárias que fazem crescer o negócio.",
"en": "Asana is the work management platform teams use to stay focused on the goals, projects, and daily tasks that grow business."
},
"website": "https://asana.com",
"signup_url": "https://asana.com/#signup",
"api_base_uri": {
"production": {
"uri": "https://app.asana.com/api/1.0",
"label": "Produção",
"default": true
}
},
"authentication": {
"type": "oauth_2",
"oauth_access_fields": {
"client_id": "PLUGA_CLIENT_ID",
"client_secret": "PLUGA_CLIENT_SECRET",
"authorize_url": "https://app.asana.com/-/oauth_authorize",
"access_token_url": "https://app.asana.com/-/oauth_token",
"refresh_token_url": "https://app.asana.com/-/oauth_token",
"access_token_placement": "header_bearer",
"response_type": "code"
},
"ping_request": {
"method_name": "/users/me",
"params": {
"opt_fields": "id"
}
}
}
}
{% endcode %}
A forma de configurá-la é basicamente o preenchimento de um aquivo JSON (lib/app.json
). Vamos passar campo a campo para entender os seus significados e seus possíveis valores.
-
app_id: Identifica sua aplicação. Essa identificação deve ser única dentro da Pluga (iremos validar se já não existe alguma aplicação com esse
app_id
). Usualmente é o nome da sua aplicação em snake_case. Por exemplo, Google Sheets seria "google_sheets", Boleto Simples seria "boleto_simples", Paypal seria "paypal" e NFe.io seria "nfe_io".\ -
name: Nome da sua aplicação e como ele será exibido. Por exemplo: NFe.io, Pagar.me e Boleto Simples.\
-
color: Referente a cor da sua aplicação na Pluga, em hexadecimal.\
-
description: Uma breve descrição sobre sua aplicação e o que ela faz, entre 20 e 50 palavras. Explique o que torna sua ferramenta única. Não precisa mencionar a Pluga aqui, foque somente em descrever o seu negócio e sua proposta de valor. Um bom exemplo é o da RD Station Marketing: "[...] o software RD Station ajuda sua empresa a gerar mais leads qualificados e vendas, além de construir uma sólida estratégia de Marketing Digital." Observe que se deve preencher todas as opções de idioma para que a aplicação seja exibida corretamente nos diferentes idiomas.\
-
website: URL para a home da aplicação.\
-
signup_url: URL para a página de cadastro da aplicação.\
-
api_base_uri: URI base para as chamadas à sua API. Como as URI base podem ser diferentes dependendo de qual ambiente da aplicação se quer interagir, este campo é um objeto que permite indicar qual URI deve ser usada para cada ambiente que se deseja interagir. No caso da Asana possuímos apenas uma URI base (
production
), porém sua aplicação pode ter uma URI base para sandbox, por exemplo.\-
uri: URI do ambiente e que será usada como base nas chamadas à API.\
-
label: Como será apresentado o ambiente para o usuário.\
-
default: Indica qual ambiente é o padrão se não houver alteração pelo usuário. Essa propriedade deve estar presente apenas em uma opção de ambiente.
-
Até o momento existem 5 formas de configurar a autenticação de uma aplicação na Pluga: oauth_2, basic_auth, pass_through_header, pass_through_query_string e no_auth (quando não há autenticação). Vamos falar sobre cada tipo de autenticação e seus respectivos parâmetros.
Abaixo temos o exemplo do JSON apenas do campo authentication
da aplicação Google Contacts para ilustrar como deve ser configurado o método de autenticação oauth_2.
{% code title="lib/app.json" %}
{
// ...
"authentication": {
"type": "oauth_2",
"oauth_access_fields": {
"client_id": "PLUGA_CLIENT_ID",
"client_secret": "PLUGA_CLIENT_SECRET",
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth",
"access_token_url": "https://www.googleapis.com/oauth2/v4/token",
"refresh_token_url": "https://www.googleapis.com/oauth2/v4/token",
"access_token_placement": "header_bearer",
"scope": [
"https://www.googleapis.com/auth/contacts"
],
"response_type": "code",
"access_type": "offline",
"prompt": "consent"
}
}
}
{% endcode %}
-
type: Tipo da autenticação. Neste caso "oauth_2", para autenticação do tipo OAuth 2.\
-
oauth_access_fields: Campo que agrupará o conjunto de campos para descrever todos os parâmetros para a autenticação OAuth 2.\
-
client_id: Chave pública de acesso da API que deve ser criada para a Pluga.\
-
client_secret: Chave secreta para acesso da API que deve ser criada para a Pluga (essa chave não será divulgada e exposta a nenhum ambiente externo ao dos servidores da Pluga).\
-
authorize_url: URL que o usuário será redirecionado.\
-
access_token_url: URL para recuperar o access token, após o usuário ter autorizado e o código temporário ter sido recuperado.\
-
refresh_token_url: [Opcional] URL para renovar o access token no caso de expiração. Para APIs onde o access token não expira, basta omitir este campo.\
-
access_token_placement: Indica como o access token deverá ser passado nas chamadas à sua API para autorizar o acesso. Os valores possíveis são:\
-
header_bearer: Para passar o access token no header das requisições como um bearer token no formato
"Authorization: Bearer {{access_token}}"
.\ -
header_basic: Para passar o access token no header da requisição como um basic token no formato
"Authorization: Basic {{access_token}}"
.\ -
query_string: Para passar o access token como parâmetro da query string no formato
"access_token={{access_token}}"
.\
-
-
access_token_on_query_string_replacement: [Opcional] Indica o nome do parâmetro que deve ser incluído na query string, só deve ser definido quando
"access_token_placement": "query_string"
e o nome do parâmetro não foraccess_token
. Um exemplo dessa situação é a API do Slack, onde o parâmetro da query string étoken
. Neste caso temos na query string o formato"token={{access_token}}"
.\ -
scope: Lista das permissões necessárias para que a Pluga tenha acesso às informações da conta do usuário na sua aplicação. Recomenda-se que essa lista seja a mais restrita possível.\
-
response_type: Nome do campo que contém o código temporário que será retornado via query string quando o usuário for redirecionado de volta pra Pluga.
-
{% hint style="info" %}
Outros campos de configuração adicionais podem ser passados através do objeto query_string
do campo authentication
, como utilizado no Jira:
{
// ...
"authentication": {
// ...
"query_string": {
"audience": "api.atlassian.com"
}
}
}
{% endhint %}
Abaixo temos o exemplo do JSON apenas do campo authentication
da aplicação Zendesk para ilustrar como deve ser configurado o método de autenticação basic_auth.
{% code title="lib/app.json" %}
{
// ...
"authentication": {
"type": "basic_auth",
"basic_auth_format": "{username}/token:{password}",
"fields": [
{
"name": "subdomain",
"label": "Subdomínio",
"type": "text",
"validations": [
{
"name": "min_length",
"value": 3
}
]
},
{
"name": "email",
"label": "Email",
"mapping": "username",
"type": "email"
},
{
"name": "token",
"label": "Token",
"mapping": "password",
"type": "text"
}
]
}
}
{% endcode %}
-
type: Tipo da autenticação. Neste caso "basic_auth", para autenticação do tipo HTTP Basic Auth passando usuário e senha no header, formato
"Authentication: Basic {{user_and_password_in_base64}}"
.\ -
basic_auth_format: [Opcional] Template que será usado para concatenar o username e o password antes de gerar o hash em base 64. Valor padrão
"{username}:{password}"
.\ -
fields: Lista dos campos que o usuário deverá preencher para realizar a autenticação e quais serão mapeados para os atributos
username
epassword
(veja exemplo acima). Cada campo é um objeto que pode conter os seguintes atributos.\-
name: Nome do campo, sempre em minúsculo e espaços substituídos por
_
, exemplo: "token", "api_key".\ -
label: Nome do campo que será exibido para o usuário.\
-
mapping: Indica qual campo se está mapeando. Os valores possíveis são
username
epassword
.\ -
type: Tipo do input que será mostrado para o usuário preencher e que também faz parte da validação. Os valores possíveis são
text
,password
eemail
.\ -
validations: Lista de condições para que o campo possa ser validado. Cada condição é um objeto que contém os seguintes atributos:\
-
name: Nome da condição desejada, os valores possíveis são:\
-
min_length: Tamanho mínimo de caracteres.\
-
max_length: Tamanho máximo de caracteres.\
-
-
value: Valor da condição. No exemplo ilustrado do primeiro campo do Zendesk, temos a condição
{ "name": "min_length", "value": 3 }
. Ou seja, o campo "subdomain" será validado apenas se o número de caracteres for maior ou igual à 3.
-
-
Abaixo temos o exemplo do JSON apenas do campo authentication
da aplicação Agendor para ilustrar como deve ser configurado o método de autenticação pass_through_header.
{% code title="lib/app.json" %}
{
// ...
"authentication": {
"type": "pass_through_header",
"fields": [
{
"name": "token",
"label": "Token para usar a API do Agendor",
"mapping": "Authorization",
"prefix": "Token",
"type": "text",
"validations": [
{
"name": "min_length",
"value": 10
}
]
}
]
}
}
{% endcode %}
-
type: Tipo da autenticação. Neste caso "pass_through_header", para enviar as chaves de autenticação como header das requisições para a sua API, exemplo
"Authentication: Bearer {{access_token}}"
.\ -
fields: Lista dos campos que o usuário deverá preencher para realizar a autenticação via header. Cada campo é um objeto que pode conter os seguintes atributos.\
-
name: Nome do campo, sempre em minúsculo e espaços substituídos por
_
, exemplo: "token", "api_key".\ -
label: Nome do campo que será exibido para o usuário.\
-
mapping: Indica qual header se está mapeando.\
-
prefix: [Opcional] Indica se há algum prefixo antes do valor preenchido pelo usuário no campo.\
-
type: Tipo do input que será mostrado para o usuário preencher e que também faz parte da validação. Os valores possíveis são
text
,password
eemail
.\ -
validations: Lista de condições para que o campo possa ser validado. Cada condição é um objeto que contém os seguintes atributos:\
-
name: Nome da condição desejada, os valores possíveis são:\
-
min_length: Tamanho mínimo de caracteres.\
-
max_length: Tamanho máximo de caracteres.\
-
-
value: Valor da condição. No exemplo ilustrado do primeiro campo do Agendor, temos a condição
{ "name": "min_length", "value": 10 }
. Ou seja, o campo "token" será validado apenas se o número de caracteres for maior ou igual à 10.
-
-
Abaixo temos o exemplo do JSON apenas do campo authentication
da aplicação Magento para ilustrar como deve ser configurado o método de autenticação pass_through_query_string.
{% code title="lib/app.json" %}
{
// ...
"authentication": {
"type": "pass_through_query_string",
"fields": [
{
"name": "site",
"label": "Site Completo (https://seusite.com)",
"type": "text",
"validations": [
{
"name": "min_length",
"value": 13
}
]
},
{
"name": "api_user",
"label": "API Username",
"type": "text"
},
{
"name": "api_key",
"label": "API Key",
"type": "password"
}
]
}
}
{% endcode %}
-
type: Tipo da autenticação. Neste caso "pass_through_query_string", para enviar as chaves de autenticação como parâmetros query string, exemplo
"access_token={{access_token}}"
.\ -
fields: Lista dos campos que o usuário deverá preencher para realizar a autenticação via query string. Cada campo é um objeto que pode conter os seguintes atributos.\
-
name: Nome do campo, sempre em minúsculo e espaços substituídos por
_
, exemplo: "token", "api_key". -
label: Nome do campo que será exibido para o usuário.\
-
type: Tipo do input que será mostrado para o usuário preencher e que também faz parte da validação. Os valores possíveis são
text
,password
eemail
.\ -
validations: Lista de condições para que o campo possa ser validado. Cada condição é um objeto que contém os seguintes atributos:\
-
name: Nome da condição desejada, os valores possíveis são:\
-
min_length: Tamanho mínimo de caracteres.\
-
max_length: Tamanho máximo de caracteres.\
-
-
value: Valor da condição. No exemplo ilustrado do primeiro campo do Agendor, temos a condição
{ "name": "min_length", "value": 13 }
. Ou seja, o campo "token" será validado apenas se o número de caracteres for maior ou igual à 10.
-
-
As vezes não existe necessidade do usuário incluir as chaves de acesso da API da sua aplicação. Nestes casos você deve configurar "type": "no_auth"
. Abaixo temos o exemplo do JSON apenas do campo authentication
da aplicação Paypal para ilustrar como deve ser configurado o método de autenticação no_auth.
{% code title="lib/app.json" %}
{
// ...
"authentication": {
"type": "no_auth"
}
}
{% endcode %}
Para que seja possível verificar se o usuário realmente incluiu chaves de acesso válidas, precisamos fazer alguma requisição para a sua API, como um ping, e a partir do retorno saber se as credenciais são válidas ou não. Para isso vamos configurar o método ping
.
O Ping da sua aplicação deve ficar no arquivo (lib/index.js
).
No arquivo index.js
você vai configurar o funcionamento dinâmico do seu Ping
. Você deve expor uma função chamada ping
que recebe 2 objetos como argumentos e retorna uma Promise, esses argumentos são:
-
plg: Objeto contendo bibliotecas auxiliares para o desenvolvimento do seu ping, como por exemplo a axios.\
-
event: Objeto contendo os dados que seu ping vai usar para resgatar os novos registros da sua API, como chaves de autenticação.
Abaixo temos a configuração do ping
da aplicação Lahar.
{% hint style="info" %} Estas são configurações comuns para todos os tipos de autenticações. {% endhint %}
{% code title="lib/index.js" %}
exports.ping = (plg, event) => plg.axios({
method: 'get',
url: `${event.meta.baseURI}/api/custom_fields`,
params: {
token_api_lahar: event.auth.token_api_lahar,
},
}).then((res) => {
const { data } = res.data;
if (data) throw new Error(data.error.message);
return data;
});
{% endcode %}
{% hint style="info" %} Como é um método para testar a validade das credenciais, é ideal que o endpoint configurado nessa requisição precise de autenticação e das mesmas permissões que serão necessárias nas requisições para a sua API que serão feitas nos triggers e actions da ferramenta. Ex: Caso o usuário digite as credenciais erradas ou não dê todas as permissões necessárias, esse método deverá retornar um erro, informando ao usuário que existe um problema de autenticação. {% endhint %}
Caso a requisição venha com um status de erro 4xx ou 5xx o ping retornará falha e o usuário será informado. Caso mesmo com as credenciais inválidas a API retorne status 200, é possível construir uma lógica no tratamento da resposta para disparar uma exceção, como é possível observar no exemplo acima.