mirror of
https://github.com/n8n-io/n8n-nodes-starter.git
synced 2025-11-01 23:52:25 -05:00
S4DSAuth node added. Some other nodes deleted
This commit is contained in:
parent
21f7bc4eae
commit
392231e695
16 changed files with 4910 additions and 222 deletions
109
nodes/S4DSAuth/AuthDescription.ts
Normal file
109
nodes/S4DSAuth/AuthDescription.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
// Operaciones disponibles para el recurso de autenticación
|
||||
export const authOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['auth'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Generate Token',
|
||||
value: 'generateToken',
|
||||
description: 'Generate authentication token using credentials',
|
||||
action: 'Generate authentication token',
|
||||
routing: {
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: '/login/generateToken',
|
||||
body: {
|
||||
username: '={{$credentials.s4dsApi.username}}',
|
||||
password: '={{$credentials.s4dsApi.password}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Validate Token',
|
||||
value: 'validateToken',
|
||||
description: 'Validate existing token',
|
||||
action: 'Validate existing token',
|
||||
routing: {
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: '/auth/validate',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
default: 'generateToken',
|
||||
},
|
||||
];
|
||||
|
||||
// Campos para la operación de generación de token
|
||||
const generateTokenOperation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['auth'],
|
||||
operation: ['generateToken'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Store Token in Context',
|
||||
name: 'storeInContext',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: 'Whether to store the token in the workflow context for other nodes to use',
|
||||
},
|
||||
{
|
||||
displayName: 'Token Context Key',
|
||||
name: 'tokenContextKey',
|
||||
type: 'string',
|
||||
default: 's4ds_token',
|
||||
description: 'Key to store the token in the workflow context',
|
||||
displayOptions: {
|
||||
show: {
|
||||
storeInContext: [true],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// Campos para la operación de validación de token
|
||||
const validateTokenOperation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Token',
|
||||
name: 'token',
|
||||
type: 'string',
|
||||
required: true,
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['auth'],
|
||||
operation: ['validateToken'],
|
||||
},
|
||||
},
|
||||
description: 'Token to validate',
|
||||
},
|
||||
];
|
||||
|
||||
// Exportar todos los campos
|
||||
export const authFields: INodeProperties[] = [
|
||||
...generateTokenOperation,
|
||||
...validateTokenOperation,
|
||||
];
|
||||
111
nodes/S4DSAuth/README.md
Normal file
111
nodes/S4DSAuth/README.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# S4DS Authentication Node
|
||||
|
||||
Este nodo permite autenticarse con las APIs de S4DS y gestionar tokens de acceso.
|
||||
|
||||
## Características
|
||||
|
||||
- **Generación de tokens**: Autenticación con usuario y contraseña
|
||||
- **Validación de tokens**: Verificar si un token es válido
|
||||
- **Múltiples ambientes**: Soporte para Test, UAT y Production
|
||||
- **Múltiples clientes**: Configuración para diferentes clientes (Demo, Cliente 1, Cliente 2)
|
||||
- **Gestión de contexto**: Almacenamiento automático de tokens para uso en otros nodos
|
||||
|
||||
## Configuración
|
||||
|
||||
### Credenciales
|
||||
|
||||
1. Configure las credenciales de S4DS API:
|
||||
- **Base URL**: Seleccione el ambiente y cliente correspondiente
|
||||
- **Username**: Nombre de usuario para autenticación
|
||||
- **Password**: Contraseña para autenticación
|
||||
- **Custom Base URL**: Para URLs personalizadas
|
||||
- **Timeout**: Tiempo de espera para las peticiones (ms)
|
||||
|
||||
### Operaciones
|
||||
|
||||
#### Generate Token
|
||||
|
||||
Genera un token de autenticación usando las credenciales configuradas.
|
||||
|
||||
**Parámetros opcionales:**
|
||||
- **Store Token in Context**: Almacenar token en el contexto del workflow
|
||||
- **Token Context Key**: Clave para almacenar el token (por defecto: `s4ds_token`)
|
||||
|
||||
**Parámetros opcionales:**
|
||||
- **Store Token in Context**: Almacenar token en el contexto del workflow
|
||||
- **Token Context Key**: Clave para almacenar el token (por defecto: `s4ds_token`)
|
||||
|
||||
**Respuesta:**
|
||||
```json
|
||||
{
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600,
|
||||
"token": "8a6c71b3-fa62-434d-8b38-907de24c3176"
|
||||
}
|
||||
```
|
||||
|
||||
#### Validate Token
|
||||
|
||||
Valida si un token existente es válido.
|
||||
|
||||
**Parámetros requeridos:**
|
||||
- **Token**: Token a validar
|
||||
|
||||
## Uso en Workflows
|
||||
|
||||
### Flujo básico de autenticación
|
||||
|
||||
1. Configure el nodo **S4DS Auth** con la operación "Generate Token"
|
||||
2. Configure las credenciales y parámetros de autenticación
|
||||
3. El token se almacenará automáticamente en el contexto del workflow
|
||||
4. Use el token en otros nodos de API S4DS
|
||||
|
||||
### Acceso al token desde otros nodos
|
||||
|
||||
El token se almacena en el contexto del workflow y puede ser accedido usando:
|
||||
|
||||
```
|
||||
{{ $context.s4ds_token }}
|
||||
```
|
||||
|
||||
O si configuró una clave personalizada:
|
||||
|
||||
```
|
||||
{{ $context.your_custom_key }}
|
||||
```
|
||||
|
||||
## URLs de API
|
||||
|
||||
### Demo
|
||||
- **Test**: `https://demotest.s4ds.com/demoapi-test`
|
||||
- **UAT**: `https://demouat.s4ds.com/demoapi-uat`
|
||||
- **Production**: `https://demoprod.s4ds.com/demoapi-prod`
|
||||
|
||||
### Cliente 1
|
||||
- **Test**: `https://cliente1test.s4ds.com/cliente1api-test`
|
||||
- **UAT**: `https://cliente1uat.s4ds.com/cliente1api-uat`
|
||||
- **Production**: `https://cliente1prod.s4ds.com/cliente1api-prod`
|
||||
|
||||
### Cliente 2
|
||||
- **Test**: `https://cliente2test.s4ds.com/cliente2api-test`
|
||||
- **UAT**: `https://cliente2uat.s4ds.com/cliente2api-uat`
|
||||
- **Production**: `https://cliente2prod.s4ds.com/cliente2api-prod`
|
||||
|
||||
## Manejo de Errores
|
||||
|
||||
El nodo maneja automáticamente:
|
||||
- Errores de autenticación (credenciales inválidas)
|
||||
- Errores de red y timeout
|
||||
- Tokens expirados
|
||||
- Errores de formato de respuesta
|
||||
|
||||
## Ejemplo de Workflow
|
||||
|
||||
```
|
||||
[S4DS Auth: Generate Token] → [HTTP Request: API Call] → [Process Data]
|
||||
```
|
||||
|
||||
En el nodo HTTP Request, configure el header de autorización:
|
||||
```
|
||||
Authorization: Bearer {{ $context.s4ds_token }}
|
||||
```
|
||||
168
nodes/S4DSAuth/S4DSAuth.node.ts
Normal file
168
nodes/S4DSAuth/S4DSAuth.node.ts
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
import { INodeType, INodeTypeDescription, NodeConnectionType, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
import { authOperations, authFields } from './AuthDescription';
|
||||
|
||||
export class S4DSAuth implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'S4DS Authentication',
|
||||
name: 's4dsAuth',
|
||||
icon: { light: 'file:s4ds.svg', dark: 'file:s4ds.svg' },
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"]}}',
|
||||
description: 'Authenticate with S4DS API and manage tokens',
|
||||
defaults: {
|
||||
name: 'S4DS Auth',
|
||||
},
|
||||
inputs: [NodeConnectionType.Main],
|
||||
outputs: [NodeConnectionType.Main],
|
||||
usableAsTool: true,
|
||||
credentials: [
|
||||
{
|
||||
name: 's4dsApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
requestDefaults: {
|
||||
baseURL: '={{$credentials.s4dsApi.baseUrl === "custom" ? $credentials.s4dsApi.customBaseUrl : $credentials.s4dsApi.baseUrl}}',
|
||||
url: '',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Authentication',
|
||||
value: 'auth',
|
||||
},
|
||||
],
|
||||
default: 'auth',
|
||||
},
|
||||
...authOperations,
|
||||
...authFields,
|
||||
],
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
try {
|
||||
const resource = this.getNodeParameter('resource', i) as string;
|
||||
const operation = this.getNodeParameter('operation', i) as string;
|
||||
|
||||
if (resource === 'auth') {
|
||||
if (operation === 'generateToken') {
|
||||
// Obtener credenciales
|
||||
const credentials = await this.getCredentials('s4dsApi');
|
||||
|
||||
// Determinar la URL base
|
||||
let baseUrl = credentials.baseUrl;
|
||||
if (baseUrl === 'custom') {
|
||||
baseUrl = credentials.customBaseUrl;
|
||||
}
|
||||
|
||||
if (!baseUrl) {
|
||||
throw new Error('Base URL is required. Please configure the S4DS API credentials.');
|
||||
}
|
||||
|
||||
// Ejecutar la petición HTTP para generar token
|
||||
const response = await this.helpers.httpRequest({
|
||||
method: 'POST',
|
||||
url: `${baseUrl}/login/generateToken`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: {
|
||||
username: credentials.username,
|
||||
password: credentials.password,
|
||||
},
|
||||
});
|
||||
|
||||
// Almacenar token en contexto
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as {
|
||||
storeInContext?: boolean;
|
||||
tokenContextKey?: string;
|
||||
};
|
||||
|
||||
const contextKey = additionalFields.tokenContextKey || 's4ds_token';
|
||||
const tokenData = {
|
||||
token: response.token,
|
||||
token_type: response.token_type,
|
||||
expires_in: response.expires_in,
|
||||
expires_at: new Date(Date.now() + response.expires_in * 1000).toISOString(),
|
||||
authorization_header: `${response.token_type} ${response.token}`,
|
||||
};
|
||||
|
||||
// Almacenar en contexto del workflow
|
||||
this.getWorkflowStaticData('global')[contextKey] = tokenData;
|
||||
|
||||
// Retornar respuesta sin el token por seguridad
|
||||
const secureResponse = {
|
||||
success: true,
|
||||
token_type: response.token_type,
|
||||
expires_in: response.expires_in,
|
||||
expires_at: tokenData.expires_at,
|
||||
message: 'Token generated successfully and stored in workflow context',
|
||||
context_key: contextKey,
|
||||
};
|
||||
|
||||
returnData.push({
|
||||
json: secureResponse,
|
||||
});
|
||||
} else if (operation === 'validateToken') {
|
||||
const token = this.getNodeParameter('token', i) as string;
|
||||
|
||||
// Obtener credenciales
|
||||
const credentials = await this.getCredentials('s4dsApi');
|
||||
|
||||
// Determinar la URL base
|
||||
let baseUrl = credentials.baseUrl;
|
||||
if (baseUrl === 'custom') {
|
||||
baseUrl = credentials.customBaseUrl;
|
||||
}
|
||||
|
||||
if (!baseUrl) {
|
||||
throw new Error('Base URL is required. Please configure the S4DS API credentials.');
|
||||
}
|
||||
|
||||
// Ejecutar validación de token
|
||||
const response = await this.helpers.httpRequest({
|
||||
method: 'GET',
|
||||
url: `${baseUrl}/auth/validate`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
returnData.push({
|
||||
json: response,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: {
|
||||
error: error.message,
|
||||
},
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
80
nodes/S4DSAuth/S4DSHelper.ts
Normal file
80
nodes/S4DSAuth/S4DSHelper.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import { IExecuteFunctions } from 'n8n-workflow';
|
||||
|
||||
export interface S4DSTokenData {
|
||||
token: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
expires_at: string;
|
||||
authorization_header: string;
|
||||
}
|
||||
|
||||
export class S4DSHelper {
|
||||
/**
|
||||
* Obtiene el token de autorización del contexto del workflow
|
||||
* @param this - Contexto de ejecución del nodo
|
||||
* @param contextKey - Clave del contexto donde está almacenado el token (por defecto: 's4ds_token')
|
||||
* @returns Objeto con datos del token incluyendo el header de autorización
|
||||
*/
|
||||
static getTokenFromContext(this: IExecuteFunctions, contextKey: string = 's4ds_token'): S4DSTokenData {
|
||||
const tokenData = this.getWorkflowStaticData('global')[contextKey] as S4DSTokenData;
|
||||
|
||||
if (!tokenData || !tokenData.token) {
|
||||
throw new Error(`No S4DS token found in context with key: ${contextKey}. Please run S4DS Auth node first.`);
|
||||
}
|
||||
|
||||
// Verificar si el token ha expirado
|
||||
if (tokenData.expires_at && new Date(tokenData.expires_at) <= new Date()) {
|
||||
throw new Error('S4DS token has expired. Please regenerate token using S4DS Auth node.');
|
||||
}
|
||||
|
||||
return tokenData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene el header de autorización listo para usar
|
||||
* @param this - Contexto de ejecución del nodo
|
||||
* @param contextKey - Clave del contexto donde está almacenado el token (por defecto: 's4ds_token')
|
||||
* @returns Header de autorización completo (ej: "Bearer 8a6c71b3-fa62-434d-8b38-907de24c3176")
|
||||
*/
|
||||
static getAuthorizationHeader(this: IExecuteFunctions, contextKey: string = 's4ds_token'): string {
|
||||
const tokenData = S4DSHelper.getTokenFromContext.call(this, contextKey);
|
||||
return tokenData.authorization_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene headers HTTP completos con autorización
|
||||
* @param this - Contexto de ejecución del nodo
|
||||
* @param contextKey - Clave del contexto donde está almacenado el token (por defecto: 's4ds_token')
|
||||
* @param additionalHeaders - Headers adicionales opcionales
|
||||
* @returns Objeto con headers HTTP completos
|
||||
*/
|
||||
static getHeadersWithAuth(
|
||||
this: IExecuteFunctions,
|
||||
contextKey: string = 's4ds_token',
|
||||
additionalHeaders: Record<string, string> = {}
|
||||
): Record<string, string> {
|
||||
const authHeader = S4DSHelper.getAuthorizationHeader.call(this, contextKey);
|
||||
|
||||
return {
|
||||
Authorization: authHeader,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...additionalHeaders,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica si existe un token válido en el contexto
|
||||
* @param this - Contexto de ejecución del nodo
|
||||
* @param contextKey - Clave del contexto donde está almacenado el token (por defecto: 's4ds_token')
|
||||
* @returns true si existe un token válido, false en caso contrario
|
||||
*/
|
||||
static hasValidToken(this: IExecuteFunctions, contextKey: string = 's4ds_token'): boolean {
|
||||
try {
|
||||
S4DSHelper.getTokenFromContext.call(this, contextKey);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
5
nodes/S4DSAuth/s4ds.svg
Normal file
5
nodes/S4DSAuth/s4ds.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
||||
<path d="M2 17l10 5 10-5"/>
|
||||
<path d="M2 12l10 5 10-5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 289 B |
Loading…
Add table
Add a link
Reference in a new issue