mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 06:34:05 -08:00
fix(editor): Remove isOwner
from IUser interface (#8888)
This commit is contained in:
parent
024be62693
commit
6955e8991c
|
@ -7,7 +7,8 @@ import type {
|
|||
REGULAR_NODE_CREATOR_VIEW,
|
||||
AI_OTHERS_NODE_CREATOR_VIEW,
|
||||
VIEWS,
|
||||
} from './constants';
|
||||
ROLE,
|
||||
} from '@/constants';
|
||||
import type { IMenuItem } from 'n8n-design-system';
|
||||
import {
|
||||
type GenericValue,
|
||||
|
@ -688,9 +689,9 @@ export type IPersonalizationSurveyVersions =
|
|||
| IPersonalizationSurveyAnswersV2
|
||||
| IPersonalizationSurveyAnswersV3;
|
||||
|
||||
export type IRole = 'default' | 'global:owner' | 'global:member' | 'global:admin';
|
||||
|
||||
export type InvitableRoleName = 'global:member' | 'global:admin';
|
||||
export type Roles = typeof ROLE;
|
||||
export type IRole = Roles[keyof Roles];
|
||||
export type InvitableRoleName = Roles['Member' | 'Admin'];
|
||||
|
||||
export interface IUserResponse {
|
||||
id: string;
|
||||
|
@ -714,7 +715,6 @@ export interface IUser extends IUserResponse {
|
|||
isDefaultUser: boolean;
|
||||
isPendingUser: boolean;
|
||||
hasRecoveryCodesLeft: boolean;
|
||||
isOwner: boolean;
|
||||
inviteAcceptUrl?: string;
|
||||
fullName?: string;
|
||||
createdAt?: string;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { parsePermissionsTable } from '@/permissions';
|
||||
import type { IUser } from '@/Interface';
|
||||
import { ROLE } from '@/constants';
|
||||
|
||||
describe('parsePermissionsTable()', () => {
|
||||
const user: IUser = {
|
||||
|
@ -7,9 +8,11 @@ describe('parsePermissionsTable()', () => {
|
|||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
isDefaultUser: false,
|
||||
isOwner: true,
|
||||
isPending: false,
|
||||
isPendingUser: false,
|
||||
mfaEnabled: false,
|
||||
hasRecoveryCodesLeft: false,
|
||||
role: ROLE.Owner,
|
||||
};
|
||||
|
||||
it('should return permissions object using generic permissions table', () => {
|
||||
|
|
|
@ -16,9 +16,6 @@ export const userFactory = Factory.extend<IUser>({
|
|||
isDefaultUser() {
|
||||
return false;
|
||||
},
|
||||
isOwner() {
|
||||
return false;
|
||||
},
|
||||
isPending() {
|
||||
return false;
|
||||
},
|
||||
|
@ -28,4 +25,10 @@ export const userFactory = Factory.extend<IUser>({
|
|||
signInType(): SignInType {
|
||||
return SignInType.EMAIL;
|
||||
},
|
||||
mfaEnabled() {
|
||||
return false;
|
||||
},
|
||||
hasRecoveryCodesLeft() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -2,8 +2,8 @@ import type {
|
|||
CurrentUserResponse,
|
||||
IPersonalizationLatestVersion,
|
||||
IRestApiContext,
|
||||
IRole,
|
||||
IUserResponse,
|
||||
InvitableRoleName,
|
||||
} from '@/Interface';
|
||||
import type { IDataObject } from 'n8n-workflow';
|
||||
import { makeRestApiRequest } from '@/utils/apiUtils';
|
||||
|
@ -157,7 +157,7 @@ export async function submitPersonalizationSurvey(
|
|||
|
||||
export interface UpdateGlobalRolePayload {
|
||||
id: string;
|
||||
newRoleName: Exclude<IRole, 'default' | 'global:owner'>;
|
||||
newRoleName: InvitableRoleName;
|
||||
}
|
||||
|
||||
export async function updateGlobalRole(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { IOnboardingCallPrompt, IUser } from '@/Interface';
|
||||
import { get, post } from '@/utils/apiUtils';
|
||||
import { isUserGlobalOwner } from '@/utils/userUtils';
|
||||
|
||||
const N8N_API_BASE_URL = 'https://api.n8n.io/api';
|
||||
const ONBOARDING_PROMPTS_ENDPOINT = '/prompts/onboarding';
|
||||
|
@ -12,7 +13,7 @@ export async function fetchNextOnboardingPrompt(
|
|||
return await get(N8N_API_BASE_URL, ONBOARDING_PROMPTS_ENDPOINT, {
|
||||
instance_id: instanceId,
|
||||
user_id: `${instanceId}#${currentUser.id}`,
|
||||
is_owner: currentUser.isOwner ?? false,
|
||||
is_owner: isUserGlobalOwner(currentUser),
|
||||
survey_results: currentUser.personalizationAnswers,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -66,8 +66,12 @@ import { mapStores } from 'pinia';
|
|||
import { useToast } from '@/composables/useToast';
|
||||
import Modal from './Modal.vue';
|
||||
import type { IFormInputs, IInviteResponse, IUser } from '@/Interface';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import { EnterpriseEditionFeature, VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from '@/constants';
|
||||
import {
|
||||
EnterpriseEditionFeature,
|
||||
VALID_EMAIL_REGEX,
|
||||
INVITE_USER_MODAL_KEY,
|
||||
ROLE,
|
||||
} from '@/constants';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
|
|||
import { useCollaborationStore } from '@/stores/collaboration.store';
|
||||
import { onBeforeUnmount, onMounted, computed, ref } from 'vue';
|
||||
import { TIME } from '@/constants';
|
||||
import { isUserGlobalOwner } from '@/utils/userUtils';
|
||||
|
||||
const collaborationStore = useCollaborationStore();
|
||||
const usersStore = useUsersStore();
|
||||
|
@ -16,7 +17,7 @@ const activeUsersSorted = computed(() => {
|
|||
const currentWorkflowUsers = (collaborationStore.getUsersForCurrentWorkflow ?? []).map(
|
||||
(userInfo) => userInfo.user,
|
||||
);
|
||||
const owner = currentWorkflowUsers.find((user) => user.role === 'global:owner');
|
||||
const owner = currentWorkflowUsers.find(isUserGlobalOwner);
|
||||
return {
|
||||
defaultGroup: owner
|
||||
? [owner, ...currentWorkflowUsers.filter((user) => user.id !== owner.id)]
|
||||
|
|
|
@ -2,7 +2,7 @@ import { merge } from 'lodash-es';
|
|||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
|
||||
import { STORES } from '@/constants';
|
||||
import { ROLE, STORES } from '@/constants';
|
||||
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import BannerStack from '@/components/banners/BannerStack.vue';
|
||||
|
@ -26,11 +26,11 @@ const initialState = {
|
|||
users: {
|
||||
'aaa-bbb': {
|
||||
id: 'aaa-bbb',
|
||||
role: 'global:owner',
|
||||
role: ROLE.Owner,
|
||||
},
|
||||
'bbb-bbb': {
|
||||
id: 'bbb-bbb',
|
||||
role: 'global:member',
|
||||
role: ROLE.Member,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { merge } from 'lodash-es';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils';
|
||||
import { STORES } from '@/constants';
|
||||
import { ROLE, STORES } from '@/constants';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import CollaborationPane from '@/components//MainHeader/CollaborationPane.vue';
|
||||
|
@ -13,10 +13,9 @@ const OWNER_USER = {
|
|||
email: 'owner@user.com',
|
||||
firstName: 'Owner',
|
||||
lastName: 'User',
|
||||
role: 'global:owner',
|
||||
role: ROLE.Owner,
|
||||
disabled: false,
|
||||
isPending: false,
|
||||
isOwner: true,
|
||||
fullName: 'Owner User',
|
||||
};
|
||||
|
||||
|
@ -26,10 +25,9 @@ const MEMBER_USER = {
|
|||
email: 'member@user.com',
|
||||
firstName: 'Member',
|
||||
lastName: 'User',
|
||||
role: 'global:member',
|
||||
role: ROLE.Member,
|
||||
disabled: false,
|
||||
isPending: false,
|
||||
isOwner: false,
|
||||
fullName: 'Member User',
|
||||
};
|
||||
|
||||
|
@ -39,10 +37,9 @@ const MEMBER_USER_2 = {
|
|||
email: 'member2@user.com',
|
||||
firstName: 'Another Member',
|
||||
lastName: 'User',
|
||||
role: 'global:member',
|
||||
role: ROLE.Member,
|
||||
disabled: false,
|
||||
isPending: false,
|
||||
isOwner: false,
|
||||
fullName: 'Another Member User',
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import PersonalizationModal from '@/components/PersonalizationModal.vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { PERSONALIZATION_MODAL_KEY, STORES, VIEWS } from '@/constants';
|
||||
import { PERSONALIZATION_MODAL_KEY, ROLE, STORES, VIEWS } from '@/constants';
|
||||
import { retry } from '@/__tests__/utils';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import { fireEvent } from '@testing-library/vue';
|
||||
|
@ -31,7 +31,7 @@ const pinia = createTestingPinia({
|
|||
isDefaultUser: false,
|
||||
isPendingUser: false,
|
||||
hasRecoveryCodesLeft: true,
|
||||
isOwner: true,
|
||||
role: ROLE.Owner,
|
||||
mfaEnabled: false,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -2,6 +2,8 @@ import { render } from '@testing-library/vue';
|
|||
import V1Banner from '../V1Banner.vue';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { ROLE } from '@/constants';
|
||||
import type { IUser } from '@/Interface';
|
||||
|
||||
describe('V1 Banner', () => {
|
||||
let pinia: ReturnType<typeof createPinia>;
|
||||
|
@ -22,8 +24,8 @@ describe('V1 Banner', () => {
|
|||
|
||||
it('should render banner with dismiss call if user is owner', () => {
|
||||
vi.spyOn(usersStore, 'currentUser', 'get').mockReturnValue({
|
||||
role: 'global:owner',
|
||||
});
|
||||
role: ROLE.Owner,
|
||||
} as IUser);
|
||||
|
||||
const { container } = render(V1Banner);
|
||||
expect(container).toMatchSnapshot();
|
||||
|
|
|
@ -752,3 +752,10 @@ export const TEMPLATES_URLS = {
|
|||
BASE_WEBSITE_URL: 'https://n8n.io/workflows',
|
||||
UTM_QUERY: 'utm_source=n8n_app&utm_medium=template_library',
|
||||
};
|
||||
|
||||
export const ROLE = {
|
||||
Owner: 'global:owner',
|
||||
Member: 'global:member',
|
||||
Admin: 'global:admin',
|
||||
Default: 'default', // default user with no email when setting up instance
|
||||
} as const;
|
||||
|
|
|
@ -8,6 +8,7 @@ import type { IUser, ICredentialsResponse, IWorkflowDb } from '@/Interface';
|
|||
import { EnterpriseEditionFeature, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { hasPermission } from './rbac/permissions';
|
||||
import { isUserGlobalOwner } from './utils/userUtils';
|
||||
|
||||
/**
|
||||
* Old permissions implementation
|
||||
|
@ -43,7 +44,7 @@ export const parsePermissionsTable = (
|
|||
table: IPermissionsTable,
|
||||
): IPermissions => {
|
||||
const genericTable: IPermissionsTable = [
|
||||
{ name: UserRole.InstanceOwner, test: () => !!user?.isOwner },
|
||||
{ name: UserRole.InstanceOwner, test: () => (user ? isUserGlobalOwner(user) : false) },
|
||||
];
|
||||
|
||||
return [...genericTable, ...table].reduce(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { hasRole } from '@/rbac/checks';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import { ROLE } from '@/constants';
|
||||
|
||||
vi.mock('@/stores/users.store', () => ({
|
||||
useUsersStore: vi.fn(),
|
||||
|
@ -12,7 +12,7 @@ describe('Checks', () => {
|
|||
vi.mocked(useUsersStore).mockReturnValue({
|
||||
currentUser: {
|
||||
isDefaultUser: false,
|
||||
role: 'global:owner',
|
||||
role: ROLE.Owner,
|
||||
},
|
||||
} as ReturnType<typeof useUsersStore>);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import type { RBACPermissionCheck, RolePermissionOptions } from '@/types/rbac';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import { ROLE } from '@/constants';
|
||||
import type { IRole } from '@/Interface';
|
||||
|
||||
export const hasRole: RBACPermissionCheck<RolePermissionOptions> = (checkRoles) => {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { roleMiddleware } from '@/rbac/middleware/role';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import type { IUser } from '@/Interface';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import { VIEWS } from '@/constants';
|
||||
import { VIEWS, ROLE } from '@/constants';
|
||||
|
||||
vi.mock('@/stores/users.store', () => ({
|
||||
useUsersStore: vi.fn(),
|
||||
|
@ -15,7 +14,7 @@ describe('Middleware', () => {
|
|||
vi.mocked(useUsersStore).mockReturnValue({
|
||||
currentUser: {
|
||||
isDefaultUser: false,
|
||||
role: 'global:owner',
|
||||
role: ROLE.Owner,
|
||||
} as IUser,
|
||||
} as ReturnType<typeof useUsersStore>);
|
||||
|
||||
|
@ -54,7 +53,7 @@ describe('Middleware', () => {
|
|||
vi.mocked(useUsersStore).mockReturnValue({
|
||||
currentUser: {
|
||||
isDefaultUser: false,
|
||||
role: 'global:owner',
|
||||
role: ROLE.Owner,
|
||||
} as IUser,
|
||||
} as ReturnType<typeof useUsersStore>);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
getNotTrialingUserResponse,
|
||||
} from './utils/cloudStoreUtils';
|
||||
import type { IRole } from '@/Interface';
|
||||
import { ROLE } from '@/constants';
|
||||
|
||||
let uiStore: ReturnType<typeof useUIStore>;
|
||||
let settingsStore: ReturnType<typeof useSettingsStore>;
|
||||
|
@ -33,7 +34,7 @@ function setUser(role: IRole) {
|
|||
}
|
||||
|
||||
function setupOwnerAndCloudDeployment() {
|
||||
setUser('global:owner');
|
||||
setUser(ROLE.Owner);
|
||||
settingsStore.setSettings(
|
||||
merge({}, SETTINGS_STORE_DEFAULT_STATE.settings, {
|
||||
n8nMetadata: {
|
||||
|
@ -75,19 +76,19 @@ describe('UI store', () => {
|
|||
[
|
||||
'default',
|
||||
'production',
|
||||
'global:owner',
|
||||
ROLE.Owner,
|
||||
'https://n8n.io/pricing?utm_campaign=utm-test-campaign&source=test_source',
|
||||
],
|
||||
[
|
||||
'default',
|
||||
'development',
|
||||
'global:owner',
|
||||
ROLE.Owner,
|
||||
'https://n8n.io/pricing?utm_campaign=utm-test-campaign&source=test_source',
|
||||
],
|
||||
[
|
||||
'cloud',
|
||||
'production',
|
||||
'global:owner',
|
||||
ROLE.Owner,
|
||||
`https://app.n8n.cloud/login?code=123&returnPath=${encodeURIComponent(
|
||||
'/account/change-plan',
|
||||
)}&utm_campaign=utm-test-campaign&source=test_source`,
|
||||
|
@ -95,7 +96,7 @@ describe('UI store', () => {
|
|||
[
|
||||
'cloud',
|
||||
'production',
|
||||
'global:member',
|
||||
ROLE.Member,
|
||||
'https://n8n.io/pricing?utm_campaign=utm-test-campaign&source=test_source',
|
||||
],
|
||||
])(
|
||||
|
|
|
@ -67,11 +67,9 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
|
|||
const getUserCloudAccount = async () => {
|
||||
if (!hasCloudPlan.value) throw new Error('User does not have a cloud plan');
|
||||
try {
|
||||
if (hasPermission(['instanceOwner'])) {
|
||||
await usersStore.fetchUserCloudAccount();
|
||||
if (!usersStore.currentUserCloudInfo?.confirmed && !userIsTrialing.value) {
|
||||
useUIStore().pushBannerToStack('EMAIL_CONFIRMATION');
|
||||
}
|
||||
await usersStore.fetchUserCloudAccount();
|
||||
if (!usersStore.currentUserCloudInfo?.confirmed && !userIsTrialing.value) {
|
||||
useUIStore().pushBannerToStack('EMAIL_CONFIRMATION');
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
|
|
|
@ -343,7 +343,6 @@ export const useUIStore = defineStore(STORES.UI, {
|
|||
let linkUrl = '';
|
||||
|
||||
const searchParams = new URLSearchParams();
|
||||
const { isInstanceOwner } = useUsersStore();
|
||||
|
||||
if (deploymentType === 'cloud' && hasPermission(['instanceOwner'])) {
|
||||
const adminPanelHost = new URL(window.location.href).host.split('.').slice(1).join('.');
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
validateSignupToken,
|
||||
updateGlobalRole,
|
||||
} from '@/api/users';
|
||||
import { PERSONALIZATION_MODAL_KEY, STORES } from '@/constants';
|
||||
import { PERSONALIZATION_MODAL_KEY, STORES, ROLE } from '@/constants';
|
||||
import type {
|
||||
Cloud,
|
||||
ICredentialsResponse,
|
||||
|
@ -46,7 +46,7 @@ import type { Scope } from '@n8n/permissions';
|
|||
import { inviteUsers, acceptInvitation } from '@/api/invitation';
|
||||
|
||||
const isPendingUser = (user: IUserResponse | null) => !!user?.isPending;
|
||||
const isInstanceOwner = (user: IUserResponse | null) => user?.role === 'global:owner';
|
||||
const isInstanceOwner = (user: IUserResponse | null) => user?.role === ROLE.Owner;
|
||||
const isDefaultUser = (user: IUserResponse | null) => isInstanceOwner(user) && isPendingUser(user);
|
||||
|
||||
export const useUsersStore = defineStore(STORES.USERS, {
|
||||
|
@ -139,7 +139,6 @@ export const useUsersStore = defineStore(STORES.USERS, {
|
|||
: undefined,
|
||||
isDefaultUser: isDefaultUser(updatedUser),
|
||||
isPendingUser: isPendingUser(updatedUser),
|
||||
isOwner: isInstanceOwner(updatedUser),
|
||||
};
|
||||
|
||||
this.users = {
|
||||
|
|
|
@ -59,6 +59,7 @@ import {
|
|||
BAMBOO_HR_NODE_TYPE,
|
||||
GOOGLE_SHEETS_NODE_TYPE,
|
||||
CODE_NODE_TYPE,
|
||||
ROLE,
|
||||
} from '@/constants';
|
||||
import type {
|
||||
IPersonalizationSurveyAnswersV1,
|
||||
|
@ -83,18 +84,13 @@ function isPersonalizationSurveyV2OrLater(
|
|||
return 'version' in data;
|
||||
}
|
||||
|
||||
export const ROLE = {
|
||||
Owner: 'global:owner',
|
||||
Member: 'global:member',
|
||||
Admin: 'global:admin',
|
||||
Default: 'default', // default user with no email when setting up instance
|
||||
} as const;
|
||||
|
||||
export const LOGIN_STATUS: { LoggedIn: ILogInStatus; LoggedOut: ILogInStatus } = {
|
||||
LoggedIn: 'LoggedIn', // Can be owner or member or default user
|
||||
LoggedOut: 'LoggedOut', // Can only be logged out if UM has been setup
|
||||
};
|
||||
|
||||
export const isUserGlobalOwner = (user: IUser): boolean => user.role === ROLE.Owner;
|
||||
|
||||
export function getPersonalizedNodeTypes(
|
||||
answers:
|
||||
| IPersonalizationSurveyAnswersV1
|
||||
|
|
|
@ -8,7 +8,6 @@ import { i18n as locale } from '@/plugins/i18n';
|
|||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { N8N_PRICING_PAGE_URL } from '@/constants';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import { hasPermission } from '@/rbac/permissions';
|
||||
|
||||
const usageStore = useUsageStore();
|
||||
|
@ -29,9 +28,7 @@ const activationKey = ref('');
|
|||
const activationKeyInput = ref<HTMLInputElement | null>(null);
|
||||
|
||||
const canUserActivateLicense = computed(() =>
|
||||
hasPermission(['role'], {
|
||||
role: [ROLE.Owner],
|
||||
}),
|
||||
hasPermission(['rbac'], { rbac: { scope: 'license:manage' } }),
|
||||
);
|
||||
|
||||
const showActivationSuccess = () => {
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { mapStores } from 'pinia';
|
||||
import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS } from '@/constants';
|
||||
import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS, ROLE } from '@/constants';
|
||||
|
||||
import type { IUser, IUserListAction, InvitableRoleName } from '@/Interface';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
|
@ -97,7 +97,6 @@ import { useUsersStore } from '@/stores/users.store';
|
|||
import { useUsageStore } from '@/stores/usage.store';
|
||||
import { useSSOStore } from '@/stores/sso.store';
|
||||
import { hasPermission } from '@/rbac/permissions';
|
||||
import { ROLE } from '@/utils/userUtils';
|
||||
import { useClipboard } from '@/composables/useClipboard';
|
||||
import type { UpdateGlobalRolePayload } from '@/api/users';
|
||||
|
||||
|
@ -324,3 +323,4 @@ export default defineComponent({
|
|||
left: calc(50% + 100px);
|
||||
}
|
||||
</style>
|
||||
IRole,
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
|||
import { useUsersStore } from '@/stores/users.store';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import { setupServer } from '@/__tests__/server';
|
||||
import { ROLE } from '@/constants';
|
||||
|
||||
let pinia: ReturnType<typeof createPinia>;
|
||||
let settingsStore: ReturnType<typeof useSettingsStore>;
|
||||
|
@ -19,7 +20,7 @@ const currentUser = {
|
|||
lastName: 'Doe',
|
||||
email: 'joh.doe@example.com',
|
||||
createdAt: Date().toString(),
|
||||
isOwner: true,
|
||||
role: ROLE.Owner,
|
||||
isDefaultUser: false,
|
||||
isPendingUser: false,
|
||||
isPending: false,
|
||||
|
|
Loading…
Reference in a new issue