fix(editor): Filter credentials by project ID also for new workflow (#9615)

This commit is contained in:
Csaba Tuncsik 2024-06-05 15:58:15 +02:00 committed by GitHub
parent e7f616290f
commit c92765dcdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 164 additions and 11 deletions

View file

@ -1,18 +1,21 @@
import { INSTANCE_ADMIN, INSTANCE_MEMBERS } from '../constants'; import { INSTANCE_ADMIN, INSTANCE_MEMBERS, INSTANCE_OWNER, MANUAL_TRIGGER_NODE_NAME, NOTION_NODE_NAME } from '../constants';
import { import {
WorkflowsPage, WorkflowsPage,
WorkflowPage, WorkflowPage,
CredentialsModal, CredentialsModal,
CredentialsPage, CredentialsPage,
WorkflowExecutionsTab, WorkflowExecutionsTab,
NDV,
} from '../pages'; } from '../pages';
import * as projects from '../composables/projects'; import * as projects from '../composables/projects';
import { getVisibleSelect } from '../utils';
const workflowsPage = new WorkflowsPage(); const workflowsPage = new WorkflowsPage();
const workflowPage = new WorkflowPage(); const workflowPage = new WorkflowPage();
const credentialsPage = new CredentialsPage(); const credentialsPage = new CredentialsPage();
const credentialsModal = new CredentialsModal(); const credentialsModal = new CredentialsModal();
const executionsTab = new WorkflowExecutionsTab(); const executionsTab = new WorkflowExecutionsTab();
const ndv = new NDV();
describe('Projects', () => { describe('Projects', () => {
before(() => { before(() => {
@ -150,9 +153,9 @@ describe('Projects', () => {
projects.getHomeButton().click(); projects.getHomeButton().click();
workflowsPage.getters.workflowCards().should('have.length', 2); workflowsPage.getters.workflowCards().should('have.length', 2);
cy.intercept('GET', '/rest/credentials*').as('credentialsListFilterless'); cy.intercept('GET', '/rest/credentials*').as('credentialsListUnfiltered');
projects.getProjectTabCredentials().click(); projects.getProjectTabCredentials().click();
cy.wait('@credentialsListFilterless').then((interception) => { cy.wait('@credentialsListUnfiltered').then((interception) => {
expect(interception.request.url).not.to.contain('filter'); expect(interception.request.url).not.to.contain('filter');
}); });
@ -228,4 +231,140 @@ describe('Projects', () => {
projects.getAddProjectButton().should('not.exist'); projects.getAddProjectButton().should('not.exist');
projects.getMenuItems().should('not.exist'); projects.getMenuItems().should('not.exist');
}); });
describe('when starting from scratch', () => {
beforeEach(() => {
cy.resetDatabase();
cy.enableFeature('sharing');
cy.enableFeature('advancedPermissions');
cy.enableFeature('projectRole:admin');
cy.enableFeature('projectRole:editor');
cy.changeQuota('maxTeamProjects', -1);
});
it('should filter credentials by project ID when creating new workflow or hard reloading an opened workflow', () => {
cy.signin(INSTANCE_OWNER);
cy.visit(workflowsPage.url);
// Create a project and add a credential to it
cy.intercept('POST', '/rest/projects').as('projectCreate');
projects.getAddProjectButton().should('contain', 'Add project').should('be.visible').click();
cy.wait('@projectCreate');
projects.getMenuItems().should('have.length', 1);
projects.getMenuItems().first().click();
projects.getProjectTabCredentials().click();
credentialsPage.getters.credentialCards().should('not.have.length');
credentialsPage.getters.emptyListCreateCredentialButton().click();
credentialsModal.getters.newCredentialModal().should('be.visible');
credentialsModal.getters.newCredentialTypeSelect().should('be.visible');
credentialsModal.getters.newCredentialTypeOption('Notion API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.connectionParameter('Internal Integration Secret').type('1234567890');
credentialsModal.actions.setName('Notion account project 1');
cy.intercept('POST', '/rest/credentials').as('credentialSave');
credentialsModal.actions.save();
cy.wait('@credentialSave').then((interception) => {
expect(interception.request.body).to.have.property('projectId');
});
credentialsModal.actions.close();
// Create another project and add a credential to it
projects.getAddProjectButton().click();
cy.wait('@projectCreate');
projects.getMenuItems().should('have.length', 2);
projects.getMenuItems().last().click();
projects.getProjectTabCredentials().click();
credentialsPage.getters.credentialCards().should('not.have.length');
credentialsPage.getters.emptyListCreateCredentialButton().click();
credentialsModal.getters.newCredentialModal().should('be.visible');
credentialsModal.getters.newCredentialTypeSelect().should('be.visible');
credentialsModal.getters.newCredentialTypeOption('Notion API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.connectionParameter('Internal Integration Secret').type('1234567890');
credentialsModal.actions.setName('Notion account project 2');
credentialsModal.actions.save();
cy.wait('@credentialSave').then((interception) => {
expect(interception.request.body).to.have.property('projectId');
});
credentialsModal.actions.close();
// Create a credential in Home project
projects.getHomeButton().click();
projects.getProjectTabCredentials().click();
credentialsPage.getters.credentialCards().should('have.length', 2);
credentialsPage.getters.createCredentialButton().click();
credentialsModal.getters.newCredentialModal().should('be.visible');
credentialsModal.getters.newCredentialTypeSelect().should('be.visible');
credentialsModal.getters.newCredentialTypeOption('Notion API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.connectionParameter('Internal Integration Secret').type('1234567890');
credentialsModal.actions.setName('Notion account personal project');
cy.intercept('POST', '/rest/credentials').as('credentialSave');
credentialsModal.actions.save();
cy.wait('@credentialSave')
credentialsModal.actions.close();
// Go to the first project and create a workflow
projects.getMenuItems().first().click();
workflowsPage.getters.workflowCards().should('not.have.length');
workflowsPage.getters.newWorkflowButtonCard().click();
workflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
workflowPage.actions.addNodeToCanvas(NOTION_NODE_NAME, true, true);
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account project 1');
ndv.getters.backToCanvas().click();
workflowPage.actions.saveWorkflowOnButtonClick();
cy.reload();
workflowPage.getters.canvasNodeByName(NOTION_NODE_NAME).should('be.visible').dblclick();
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account project 1');
ndv.getters.backToCanvas().click();
// Go to the second project and create a workflow
projects.getMenuItems().last().click();
workflowsPage.getters.workflowCards().should('not.have.length');
workflowsPage.getters.newWorkflowButtonCard().click();
workflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
workflowPage.actions.addNodeToCanvas(NOTION_NODE_NAME, true, true);
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account project 2');
ndv.getters.backToCanvas().click();
workflowPage.actions.saveWorkflowOnButtonClick();
cy.reload();
workflowPage.getters.canvasNodeByName(NOTION_NODE_NAME).should('be.visible').dblclick();
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account project 2');
ndv.getters.backToCanvas().click();
// Go to the Home project and create a workflow
projects.getHomeButton().click();
projects.getProjectTabCredentials().click();
credentialsPage.getters.credentialCards().should('have.length', 3);
projects.getProjectTabWorkflows().click();
workflowsPage.getters.workflowCards().should('have.length', 2);
workflowsPage.getters.createWorkflowButton().click();
workflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
workflowPage.actions.addNodeToCanvas(NOTION_NODE_NAME, true, true);
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account personal project');
ndv.getters.backToCanvas().click();
workflowPage.actions.saveWorkflowOnButtonClick();
cy.reload();
workflowPage.getters.canvasNodeByName(NOTION_NODE_NAME).should('be.visible').dblclick();
workflowPage.getters.nodeCredentialsSelect().first().click();
getVisibleSelect().find('li').should('have.length', 2).first().should('contain.text', 'Notion account personal project');
});
});
}); });

View file

@ -28,9 +28,10 @@ export async function getCredentialsNewName(
export async function getAllCredentials( export async function getAllCredentials(
context: IRestApiContext, context: IRestApiContext,
filter?: object, filter?: object,
includeScopes?: boolean,
): Promise<ICredentialsResponse[]> { ): Promise<ICredentialsResponse[]> {
return await makeRestApiRequest(context, 'GET', '/credentials', { return await makeRestApiRequest(context, 'GET', '/credentials', {
includeScopes: true, ...(includeScopes ? { includeScopes } : {}),
...(filter ? { filter } : {}), ...(filter ? { filter } : {}),
}); });
} }

View file

@ -247,7 +247,10 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
const credentialTypes = await getCredentialTypes(rootStore.getBaseUrl); const credentialTypes = await getCredentialTypes(rootStore.getBaseUrl);
this.setCredentialTypes(credentialTypes); this.setCredentialTypes(credentialTypes);
}, },
async fetchAllCredentials(projectId?: string): Promise<ICredentialsResponse[]> { async fetchAllCredentials(
projectId?: string,
includeScopes = true,
): Promise<ICredentialsResponse[]> {
const rootStore = useRootStore(); const rootStore = useRootStore();
const filter = { const filter = {
@ -257,6 +260,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
const credentials = await getAllCredentials( const credentials = await getAllCredentials(
rootStore.getRestApiContext, rootStore.getRestApiContext,
isEmpty(filter) ? undefined : filter, isEmpty(filter) ? undefined : filter,
includeScopes,
); );
this.setCredentials(credentials); this.setCredentials(credentials);
return credentials; return credentials;

View file

@ -3794,7 +3794,6 @@ export default defineComponent({
return; return;
} }
} }
await this.loadCredentials();
// Load a workflow // Load a workflow
let workflowId = null as string | null; let workflowId = null as string | null;
if (this.$route.params.name) { if (this.$route.params.name) {
@ -3838,6 +3837,7 @@ export default defineComponent({
await this.newWorkflow(); await this.newWorkflow();
} }
} }
await this.loadCredentials();
this.historyStore.reset(); this.historyStore.reset();
this.uiStore.nodeViewInitialized = true; this.uiStore.nodeViewInitialized = true;
document.addEventListener('keydown', this.keyDown); document.addEventListener('keydown', this.keyDown);
@ -4789,11 +4789,20 @@ export default defineComponent({
}, },
async loadCredentials(): Promise<void> { async loadCredentials(): Promise<void> {
const workflow = this.workflowsStore.getWorkflowById(this.currentWorkflow); const workflow = this.workflowsStore.getWorkflowById(this.currentWorkflow);
const projectId = let projectId: string | undefined;
workflow?.homeProject?.type === ProjectTypes.Personal if (workflow) {
projectId =
workflow.homeProject?.type === ProjectTypes.Personal
? this.projectsStore.personalProject?.id ? this.projectsStore.personalProject?.id
: workflow?.homeProject?.id; : workflow?.homeProject?.id ?? this.projectsStore.currentProjectId;
await this.credentialsStore.fetchAllCredentials(projectId); } else {
const queryParam =
typeof this.$route.query?.projectId === 'string'
? this.$route.query?.projectId
: undefined;
projectId = queryParam ?? this.projectsStore.personalProject?.id;
}
await this.credentialsStore.fetchAllCredentials(projectId, false);
}, },
async loadVariables(): Promise<void> { async loadVariables(): Promise<void> {
await this.environmentsStore.fetchAllVariables(); await this.environmentsStore.fetchAllVariables();