Skip to content

Commit 972bf0d

Browse files
authored
[SWB-75]-Fixed n8n Test Credential Logic (#9)
1 parent 049e98c commit 972bf0d

File tree

3 files changed

+279
-3
lines changed

3 files changed

+279
-3
lines changed

.github/copilot-instructions.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# Copilot Instructions for n8n-nodes-jupiterone
2+
3+
You are reviewing code for an n8n community node package that integrates with JupiterOne security platform.
4+
5+
## Repository Context
6+
- **Type**: n8n community node package
7+
- **Purpose**: JupiterOne API integration (security/compliance platform)
8+
- **Language**: TypeScript with strict mode
9+
- **Architecture**: Credentials + Query Node + Webhook Node
10+
11+
## Review Priority Levels
12+
13+
### 🚨 CRITICAL - Must Fix Immediately
14+
- Security vulnerabilities in credential handling
15+
- Type safety violations (any types, implicit returns)
16+
- Authentication bypass or credential exposure
17+
- API endpoint security issues
18+
- Error handling that exposes sensitive data
19+
20+
### ⚠️ HIGH - Should Fix Before Merge
21+
- n8n compliance violations
22+
- Performance issues (memory leaks, inefficient loops)
23+
- Poor user experience (unclear errors, missing validation)
24+
- Inappropriate logging of sensitive data
25+
- Missing input validation
26+
27+
### 🔧 MEDIUM - Nice to Fix
28+
- Code consistency and formatting
29+
- Documentation gaps
30+
- Error handling improvements
31+
- Type definition enhancements
32+
- Test coverage gaps
33+
34+
## n8n Framework Requirements
35+
36+
### Credential Files (`.credentials.ts`)
37+
**REQUIRED:**
38+
- Implement `ICredentialType` interface
39+
- Include `authenticate` configuration
40+
- Use `typeOptions: { password: true }` for sensitive fields
41+
- Follow naming: `jupiteroneApi` (not `JupiterOneApi`)
42+
- Provide `test` property for validation
43+
44+
### Node Files (`.node.ts`)
45+
**REQUIRED:**
46+
- Implement `INodeType` interface
47+
- Complete `description` object with all fields
48+
- Use `NodeConnectionType.Main` for I/O
49+
- Implement `execute()` method (regular nodes)
50+
- Implement `webhook()` method (webhook nodes)
51+
- Use `NodeApiError` for error handling
52+
53+
### Security Requirements
54+
**CRITICAL:**
55+
- Validate ALL user inputs before API calls
56+
- Use `this.getCredentials()` for secure access
57+
- NEVER log sensitive data (tokens, passwords)
58+
- Handle authentication errors gracefully
59+
- Validate API responses before processing
60+
61+
## Code Quality Standards
62+
63+
### TypeScript Requirements
64+
**MANDATORY:**
65+
- Use strict TypeScript (`strict: true`)
66+
- NO `any` types - use proper interfaces
67+
- Handle null/undefined explicitly
68+
- Use proper type assertions
69+
- Implement error types and interfaces
70+
71+
### Code Structure
72+
**REQUIRED:**
73+
- Consistent naming conventions
74+
- Meaningful variable/function names
75+
- Organize imports (n8n types first)
76+
- Use constants for magic values
77+
- Implement error boundaries
78+
79+
### Error Handling
80+
**CRITICAL:**
81+
- Catch ALL potential errors
82+
- User-friendly error messages
83+
- Appropriate logging (no sensitive data)
84+
- Don't expose internal details
85+
- Validate API responses
86+
87+
## JupiterOne Integration Requirements
88+
89+
### API Integration
90+
**REQUIRED:**
91+
- Handle API rate limits gracefully
92+
- Validate J1QL queries before execution
93+
- Implement pagination for large results
94+
- Handle GraphQL errors properly
95+
- Use appropriate timeouts
96+
97+
### Data Processing
98+
**REQUIRED:**
99+
- Validate query results before returning
100+
- Handle empty/malformed responses
101+
- Implement data transformation
102+
- Respect data limits and constraints
103+
104+
## Common Anti-Patterns (REJECT THESE)
105+
106+
### 🔴 Security Violations
107+
```typescript
108+
// ❌ REJECT: Logging sensitive data
109+
this.logger.info(`Token: ${accessToken}`);
110+
111+
// ✅ ACCEPT: Redacted logging
112+
this.logger.info('Authorization: Bearer [REDACTED]');
113+
```
114+
115+
### 🔴 Type Safety Violations
116+
```typescript
117+
// ❌ REJECT: Using any types
118+
const data: any = response.data;
119+
120+
// ✅ ACCEPT: Proper interfaces
121+
const data: JupiterOneResponse = response.data;
122+
```
123+
124+
### 🔴 Error Handling Violations
125+
```typescript
126+
// ❌ REJECT: Ignoring errors
127+
const result = await apiCall();
128+
129+
// ✅ ACCEPT: Proper error handling
130+
try {
131+
const result = await apiCall();
132+
} catch (error) {
133+
throw new NodeApiError(this.getNode(), {
134+
message: 'API call failed',
135+
description: error.message,
136+
});
137+
}
138+
```
139+
140+
### 🔴 Input Validation Violations
141+
```typescript
142+
// ❌ REJECT: No input validation
143+
const query = this.getNodeParameter('query');
144+
145+
// ✅ ACCEPT: Input validation
146+
const query = this.getNodeParameter('query') as string;
147+
if (!query || query.trim().length === 0) {
148+
throw new NodeApiError(this.getNode(), {
149+
message: 'Query parameter is required',
150+
});
151+
}
152+
```
153+
154+
## Performance Anti-Patterns (REJECT THESE)
155+
156+
### 🔴 Inefficient Processing
157+
```typescript
158+
// ❌ REJECT: Blocking async operations
159+
for (let i = 0; i < items.length; i++) {
160+
await processItem(items[i]); // Blocks execution
161+
}
162+
163+
// ✅ ACCEPT: Parallel processing
164+
const promises = items.map(item => processItem(item));
165+
const results = await Promise.all(promises);
166+
```
167+
168+
### 🔴 Memory Issues
169+
```typescript
170+
// ❌ REJECT: Accumulating large arrays
171+
let allResults = [];
172+
for (const item of items) {
173+
allResults.push(await processItem(item));
174+
}
175+
176+
// ✅ ACCEPT: Batch processing
177+
const batchSize = 100;
178+
for (let i = 0; i < items.length; i += batchSize) {
179+
const batch = items.slice(i, i + batchSize);
180+
// Process batch
181+
}
182+
```
183+
184+
## Testing Requirements
185+
186+
### Credential Testing
187+
**REQUIRED:**
188+
- Test authentication flow
189+
- Validate all credential fields
190+
- Handle test failures gracefully
191+
- Use appropriate test endpoints
192+
193+
### Node Testing
194+
**REQUIRED:**
195+
- Validate all input parameters
196+
- Handle edge cases (empty inputs, large datasets)
197+
- Test error scenarios
198+
- Validate output data structure
199+
200+
## Documentation Requirements
201+
202+
### Code Comments
203+
**REQUIRED:**
204+
- Document complex business logic
205+
- Explain JupiterOne-specific concepts
206+
- Provide usage examples
207+
- Document error handling strategies
208+
209+
### User Documentation
210+
**REQUIRED:**
211+
- Clear parameter descriptions
212+
- Example values and formats
213+
- Document limitations/constraints
214+
- Provide troubleshooting guidance
215+
216+
## Review Checklist (Use This)
217+
218+
### Pre-Approval Checklist
219+
- [ ] TypeScript errors resolved
220+
- [ ] ESLint rules passing
221+
- [ ] No security vulnerabilities
222+
- [ ] Proper error handling implemented
223+
- [ ] Input validation in place
224+
- [ ] Sensitive data not logged
225+
- [ ] n8n standards followed
226+
- [ ] JupiterOne API best practices followed
227+
- [ ] Performance considerations addressed
228+
- [ ] Documentation updated
229+
230+
### Key Review Questions
231+
1. **Security**: Could this expose sensitive information?
232+
2. **Type Safety**: Are types properly defined and used?
233+
3. **Error Handling**: Are all error cases handled?
234+
4. **Performance**: Could this cause performance issues?
235+
5. **User Experience**: Is error messaging clear?
236+
6. **n8n Compliance**: Follows community standards?
237+
7. **JupiterOne Integration**: Best API interaction method?
238+
239+
## Quick Reference Links
240+
- [n8n Community Nodes](https://docs.n8n.io/integrations/#community-nodes)
241+
- [n8n Workflow Types](https://docs.n8n.io/api/)
242+
- [JupiterOne API Docs](https://docs.jupiterone.io/)
243+
- [TypeScript Best Practices](https://www.typescriptlang.org/docs/)
244+
- [ESLint n8n Rules](https://github.com/n8n-io/eslint-plugin-n8n-nodes-base)
245+
246+
---
247+
248+
**REMEMBER**: This is a SECURITY-FOCUSED JupiterOne integration.
249+
- 🚨 Security first
250+
- 🔒 Type safety required
251+
- 👥 User experience matters
252+
- 📋 n8n compliance mandatory

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ To obtain your API token, log in to JupiterOne and generate an access token from
6969

7070
## Version history
7171

72+
- 0.1.6
73+
- Fixed Test Credential Logic, Added copilot-instructions.md
7274

7375
- 0.1.5
7476
- Removed Credential Test for J1 API

credentials/JupiterOneApi.credentials.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
import { IAuthenticateGeneric, ICredentialType, INodeProperties, Icon } from 'n8n-workflow';
1+
import {
2+
IAuthenticateGeneric,
3+
ICredentialType,
4+
INodeProperties,
5+
Icon,
6+
ICredentialTestRequest,
7+
} from 'n8n-workflow';
28

39
export class JupiterOneApi implements ICredentialType {
410
name = 'jupiteroneApi';
511
displayName = 'JupiterOne API';
612
icon = 'file:jupiterone.svg' as Icon;
7-
documentationUrl = 'https://docs.jupiterone.io/integrations/outbound-directory/n8n-community-node';
13+
documentationUrl =
14+
'https://docs.jupiterone.io/integrations/outbound-directory/n8n-community-node';
815

916
properties: INodeProperties[] = [
1017
{
@@ -40,9 +47,24 @@ export class JupiterOneApi implements ICredentialType {
4047
type: 'generic',
4148
properties: {
4249
headers: {
43-
Authorization: 'Bearer {{ $credentials.accessToken }}',
50+
Authorization: '=Bearer {{ $credentials.accessToken }}',
4451
'Content-Type': 'application/json',
4552
},
4653
},
4754
};
55+
56+
test: ICredentialTestRequest = {
57+
request: {
58+
method: 'POST',
59+
url: '={{ $credentials.apiBaseUrl }}/graphql',
60+
headers: {
61+
'JupiterOne-Account': '={{ $credentials.accountId }}',
62+
'Content-Type': 'application/json',
63+
},
64+
body: JSON.stringify({
65+
query: 'query TestQuery { __typename }',
66+
variables: {},
67+
}),
68+
},
69+
};
4870
}

0 commit comments

Comments
 (0)