fix(editor): Fix Admin panel icon in the sidebar for cloud deployments (no-changelog) (#7738)

Co-authored-by: ricardo <ricardoespinoza105@gmail.com>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-11-17 14:44:47 +01:00 committed by GitHub
parent b66b8c18e9
commit 2d039010db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 41 additions and 77 deletions

View file

@ -64,4 +64,20 @@ describe('BannerStack', { disableAutoLogin: true }, () => {
mainSidebar.actions.signout();
});
it('Should show admin button', () => {
cy.intercept('GET', '/rest/settings', (req) => {
req.on('response', (res) => {
res.send({
data: { ...res.body.data, deployment: { type: 'cloud' }, n8nMetadata: { userId: 1 } },
});
});
}).as('loadSettings');
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
cy.visit(workflowPage.url);
mainSidebar.getters.adminPanel().should('be.visible');
});
});

View file

@ -12,6 +12,7 @@ export class MainSidebar extends BasePage {
workflows: () => this.getters.menuItem('Workflows'),
credentials: () => this.getters.menuItem('Credentials'),
executions: () => this.getters.menuItem('Executions'),
adminPanel: () => this.getters.menuItem('Admin Panel'),
userMenu: () => cy.get('div[class="action-dropdown-container"]'),
logo: () => cy.getByTestId('n8n-logo'),
};

View file

@ -60,8 +60,6 @@ import {
} from '@/stores';
import { useHistoryHelper } from '@/composables/useHistoryHelper';
import { useRoute } from 'vue-router';
import type { ExternalHooks } from '@/types';
import type { PartialDeep } from 'type-fest';
import { runExternalHook } from '@/utils';
export default defineComponent({
@ -136,19 +134,10 @@ export default defineComponent({
}
},
async initializeHooks(): Promise<void> {
const hooksImports = [];
if (this.settingsStore.isCloudDeployment) {
hooksImports.push(
import('./hooks/cloud').then(
({ n8nCloudHooks }: { n8nCloudHooks: PartialDeep<ExternalHooks> }) => {
extendExternalHooks(n8nCloudHooks);
},
),
);
const { n8nCloudHooks } = await import('@/hooks/cloud');
extendExternalHooks(n8nCloudHooks);
}
await Promise.allSettled(hooksImports);
},
async onAfterAuthenticate() {
if (this.onAfterAuthenticateInitialized) {
@ -160,7 +149,6 @@ export default defineComponent({
}
await Promise.all([
this.initializeCloudData(),
this.initializeSourceControl(),
this.initializeTemplates(),
this.initializeNodeTranslationHeaders(),
@ -172,7 +160,9 @@ export default defineComponent({
async mounted() {
this.logHiringBanner();
await this.settingsStore.initialize();
await this.initializeHooks();
await this.initializeCloudData();
void this.checkForNewVersions();
void this.onAfterAuthenticate();

View file

@ -270,6 +270,14 @@ export default defineComponent({
this.settingsStore.isQueueModeEnabled && this.settingsStore.isWorkerViewAvailable,
activateOnRouteNames: [VIEWS.WORKER_VIEW],
},
{
id: 'cloud-admin',
type: 'link',
position: 'bottom',
label: 'Admin Panel',
icon: 'home',
available: this.settingsStore.isCloudDeployment && this.usersStore.isInstanceOwner,
},
{
id: 'settings',
icon: 'cog',
@ -461,6 +469,10 @@ export default defineComponent({
this.uiStore.openModal(ABOUT_MODAL_KEY);
break;
}
case 'cloud-admin': {
this.cloudPlanStore.redirectToDashboard();
break;
}
case 'quickstart':
case 'docs':
case 'forum':

View file

@ -1,4 +1,4 @@
import { hooksAddAdminIcon, hooksAddFakeDoorFeatures } from '@/hooks/utils';
import { hooksAddFakeDoorFeatures } from '@/hooks/utils';
import {
getAuthenticationModalEventData,
getExpressionEditorEventsData,
@ -29,9 +29,6 @@ import type { ExternalHooks } from '@/types';
export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
app: {
mount: [
() => {
hooksAddAdminIcon();
},
() => {
hooksAddFakeDoorFeatures();
},
@ -43,9 +40,6 @@ export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
const segmentStore = useSegment();
segmentStore.identify();
},
() => {
hooksAddAdminIcon();
},
],
createNodeActiveChanged: [
(_, meta) => {

View file

@ -1,38 +0,0 @@
import { useUIStore } from '@/stores/ui.store';
import type { IMenuItem } from 'n8n-design-system/types';
import { useUsersStore } from '@/stores/users.store';
import { addAutoLoginToAdminPanelButton } from '@/hooks/utils/hooksAddAutoLoginToAdminPanelButton';
let adminIconAdded = false;
export const hooksAddAdminIcon = () => {
if (adminIconAdded) {
return;
}
const uiStore = useUIStore();
const usersStore = useUsersStore();
if (usersStore?.globalRoleName !== 'owner') {
return;
}
const menuItems: IMenuItem[] = [
{
id: 'admin',
type: 'link',
position: 'bottom',
label: 'Admin Panel',
icon: 'home',
properties: {
href: 'https://app.n8n.cloud',
newWindow: false,
},
},
];
addAutoLoginToAdminPanelButton();
uiStore.sidebarMenuItems = [...uiStore.sidebarMenuItems, ...menuItems] as IMenuItem[];
adminIconAdded = true;
};

View file

@ -1,15 +0,0 @@
export function addAutoLoginToAdminPanelButton() {
const adminPanelHost = new URL(window.location.href).host.split('.').slice(1).join('.');
document.body?.addEventListener('click', async (e) => {
if (!e.target || !(e.target instanceof Element)) return;
if (e.target.getAttribute('id') !== 'admin' && !e.target.closest('#admin')) return;
e.preventDefault();
const restPath = window.REST_ENDPOINT ?? 'rest';
const response = await fetch(`/${restPath}/cloud/proxy/login/code`);
const { code } = await response.json();
window.location.href = `https://${adminPanelHost}/login?code=${code}`;
});
}

View file

@ -1,4 +1,2 @@
export * from './hooksAddAdminIcon';
export * from './hooksAddAutoLoginToAdminPanelButton';
export * from './hooksAddFakeDoorFeatures';
export * from './hooksNodesPanel';

View file

@ -897,7 +897,6 @@ router.beforeEach(async (to, from, next) => {
const settingsStore = useSettingsStore();
const usersStore = useUsersStore();
await settingsStore.initialize();
await usersStore.initialize();
/**

View file

@ -151,6 +151,12 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
} catch {}
};
const redirectToDashboard = async () => {
const adminPanelHost = new URL(window.location.href).host.split('.').slice(1).join('.');
const { code } = await getAutoLoginCode();
window.location.href = `https://${adminPanelHost}/login?code=${code}`;
};
return {
state,
getOwnerCurrentPlan,
@ -166,5 +172,6 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
checkForCloudPlanData,
fetchUserCloudAccount,
getAutoLoginCode,
redirectToDashboard,
};
});