Skip to content

Commit 7ad409d

Browse files
committed
prevent resource state import without open cfn template
1 parent 52d7d00 commit 7ad409d

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

src/handlers/ResourceHandler.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { randomUUID } from 'crypto';
2-
import { ServerRequestHandler } from 'vscode-languageserver';
2+
import { ResponseError, ServerRequestHandler } from 'vscode-languageserver';
33
import { RequestHandler } from 'vscode-languageserver/node';
44
import { TopLevelSection } from '../context/ContextType';
55
import { getEntityMap } from '../context/SectionContextBuilder';
@@ -79,9 +79,12 @@ export function listResourcesHandler(
7979

8080
export function importResourceStateHandler(
8181
components: ServerComponents,
82-
): ServerRequestHandler<ResourceStateParams, ResourceStateResult, never, void> {
82+
): RequestHandler<ResourceStateParams, ResourceStateResult, void> {
8383
return async (params: ResourceStateParams): Promise<ResourceStateResult> => {
8484
components.usageTracker.track(EventType.DidImportResources);
85+
if (!components.documentManager.get(params.textDocument.uri)?.isTemplate()) {
86+
throw new ResponseError(400, 'Must open CloudFormation template to import or clone resource state');
87+
}
8588
return await components.resourceStateImporter.importResourceState(params);
8689
};
8790
}

tst/unit/handlers/ResourceHandler.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import { describe, it, expect, beforeEach, vi } from 'vitest';
2-
import { CancellationToken } from 'vscode-languageserver-protocol';
2+
import { CancellationToken, RequestHandler } from 'vscode-languageserver-protocol';
3+
import { TextDocument } from 'vscode-languageserver-textdocument';
34
import { getEntityMap } from '../../../src/context/SectionContextBuilder';
5+
import { Document } from '../../../src/document/Document';
46
import {
57
getManagedResourceStackTemplateHandler,
8+
importResourceStateHandler,
69
removeResourceTypeHandler,
710
} from '../../../src/handlers/ResourceHandler';
11+
import {
12+
ResourceStateParams,
13+
ResourceStatePurpose,
14+
ResourceStateResult,
15+
} from '../../../src/resourceState/ResourceStateTypes';
816
import { GetStackTemplateParams } from '../../../src/stacks/StackRequestType';
917
import { createMockComponents } from '../../utils/MockServerComponents';
1018

@@ -156,3 +164,37 @@ describe('ResourceHandler - removeResourceTypeHandler', () => {
156164
expect(() => handler(undefined as any)).toThrow();
157165
});
158166
});
167+
168+
describe('ResourceHandler - importResourceStateHandler', () => {
169+
let mockComponents: ReturnType<typeof createMockComponents>;
170+
let handler: RequestHandler<ResourceStateParams, ResourceStateResult, void>;
171+
172+
beforeEach(() => {
173+
vi.clearAllMocks();
174+
mockComponents = createMockComponents();
175+
handler = importResourceStateHandler(mockComponents);
176+
});
177+
178+
it('should throw error if template file is not open', async () => {
179+
mockComponents.documentManager.get.returns(
180+
new Document(TextDocument.create('sample.yaml', 'yaml', 1, 'Hello:')),
181+
);
182+
mockComponents.documentManager.isTemplate.resolves(false);
183+
184+
await expect(async () => {
185+
await handler(
186+
{
187+
textDocument: { uri: 'docUri' },
188+
resourceSelections: [
189+
{
190+
resourceType: 'AWS::S3::Bucket',
191+
resourceIdentifiers: ['bucket1234'],
192+
},
193+
],
194+
purpose: ResourceStatePurpose.IMPORT,
195+
},
196+
CancellationToken.None,
197+
);
198+
}).rejects.toThrow('Must open CloudFormation template to import or clone resource state');
199+
});
200+
});

0 commit comments

Comments
 (0)