Browse Source

feat(core): Expose assignable Permissions via ServerConfig type

Relates to #450
Michael Bromley 5 years ago
parent
commit
ab2f62cd07

+ 25 - 24
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -1991,60 +1991,60 @@ export enum DeletionResult {
 export enum Permission {
   /** Authenticated means simply that the user is logged in */
   Authenticated = 'Authenticated',
-  /** Grants permission to Create Administrator */
+  /** Grants permission to create Administrator */
   CreateAdministrator = 'CreateAdministrator',
-  /** Grants permission to Create Catalog */
+  /** Grants permission to create Catalog */
   CreateCatalog = 'CreateCatalog',
-  /** Grants permission to Create Customer */
+  /** Grants permission to create Customer */
   CreateCustomer = 'CreateCustomer',
-  /** Grants permission to Create Order */
+  /** Grants permission to create Order */
   CreateOrder = 'CreateOrder',
-  /** Grants permission to Create Promotion */
+  /** Grants permission to create Promotion */
   CreatePromotion = 'CreatePromotion',
-  /** Grants permission to Create Settings */
+  /** Grants permission to create Settings */
   CreateSettings = 'CreateSettings',
-  /** Grants permission to Delete Administrator */
+  /** Grants permission to delete Administrator */
   DeleteAdministrator = 'DeleteAdministrator',
-  /** Grants permission to Delete Catalog */
+  /** Grants permission to delete Catalog */
   DeleteCatalog = 'DeleteCatalog',
-  /** Grants permission to Delete Customer */
+  /** Grants permission to delete Customer */
   DeleteCustomer = 'DeleteCustomer',
-  /** Grants permission to Delete Order */
+  /** Grants permission to delete Order */
   DeleteOrder = 'DeleteOrder',
-  /** Grants permission to Delete Promotion */
+  /** Grants permission to delete Promotion */
   DeletePromotion = 'DeletePromotion',
-  /** Grants permission to Delete Settings */
+  /** Grants permission to delete Settings */
   DeleteSettings = 'DeleteSettings',
   /** Owner means the user owns this entity, e.g. a Customer's own Order */
   Owner = 'Owner',
   Placeholder = 'Placeholder',
   /** Public means any unauthenticated user may perform the operation */
   Public = 'Public',
-  /** Grants permission to Read Administrator */
+  /** Grants permission to read Administrator */
   ReadAdministrator = 'ReadAdministrator',
-  /** Grants permission to Read Catalog */
+  /** Grants permission to read Catalog */
   ReadCatalog = 'ReadCatalog',
-  /** Grants permission to Read Customer */
+  /** Grants permission to read Customer */
   ReadCustomer = 'ReadCustomer',
-  /** Grants permission to Read Order */
+  /** Grants permission to read Order */
   ReadOrder = 'ReadOrder',
-  /** Grants permission to Read Promotion */
+  /** Grants permission to read Promotion */
   ReadPromotion = 'ReadPromotion',
-  /** Grants permission to Read Settings */
+  /** Grants permission to read Settings */
   ReadSettings = 'ReadSettings',
   /** SuperAdmin has unrestricted access to all operations */
   SuperAdmin = 'SuperAdmin',
-  /** Grants permission to Update Administrator */
+  /** Grants permission to update Administrator */
   UpdateAdministrator = 'UpdateAdministrator',
-  /** Grants permission to Update Catalog */
+  /** Grants permission to update Catalog */
   UpdateCatalog = 'UpdateCatalog',
-  /** Grants permission to Update Customer */
+  /** Grants permission to update Customer */
   UpdateCustomer = 'UpdateCustomer',
-  /** Grants permission to Update Order */
+  /** Grants permission to update Order */
   UpdateOrder = 'UpdateOrder',
-  /** Grants permission to Update Promotion */
+  /** Grants permission to update Promotion */
   UpdatePromotion = 'UpdatePromotion',
-  /** Grants permission to Update Settings */
+  /** Grants permission to update Settings */
   UpdateSettings = 'UpdateSettings'
 }
 
@@ -3237,6 +3237,7 @@ export type ServerConfig = {
   __typename?: 'ServerConfig';
   orderProcess: Array<OrderProcessState>;
   permittedAssetTypes: Array<Scalars['String']>;
+  permissions: Array<Permission>;
   customFieldConfig: CustomFields;
 };
 

+ 31 - 24
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -1811,53 +1811,53 @@ export enum Permission {
     Owner = 'Owner',
     /** Public means any unauthenticated user may perform the operation */
     Public = 'Public',
-    /** Grants permission to Create Catalog */
+    /** Grants permission to create Catalog */
     CreateCatalog = 'CreateCatalog',
-    /** Grants permission to Read Catalog */
+    /** Grants permission to read Catalog */
     ReadCatalog = 'ReadCatalog',
-    /** Grants permission to Update Catalog */
+    /** Grants permission to update Catalog */
     UpdateCatalog = 'UpdateCatalog',
-    /** Grants permission to Delete Catalog */
+    /** Grants permission to delete Catalog */
     DeleteCatalog = 'DeleteCatalog',
-    /** Grants permission to Create Customer */
+    /** Grants permission to create Customer */
     CreateCustomer = 'CreateCustomer',
-    /** Grants permission to Read Customer */
+    /** Grants permission to read Customer */
     ReadCustomer = 'ReadCustomer',
-    /** Grants permission to Update Customer */
+    /** Grants permission to update Customer */
     UpdateCustomer = 'UpdateCustomer',
-    /** Grants permission to Delete Customer */
+    /** Grants permission to delete Customer */
     DeleteCustomer = 'DeleteCustomer',
-    /** Grants permission to Create Administrator */
+    /** Grants permission to create Administrator */
     CreateAdministrator = 'CreateAdministrator',
-    /** Grants permission to Read Administrator */
+    /** Grants permission to read Administrator */
     ReadAdministrator = 'ReadAdministrator',
-    /** Grants permission to Update Administrator */
+    /** Grants permission to update Administrator */
     UpdateAdministrator = 'UpdateAdministrator',
-    /** Grants permission to Delete Administrator */
+    /** Grants permission to delete Administrator */
     DeleteAdministrator = 'DeleteAdministrator',
-    /** Grants permission to Create Order */
+    /** Grants permission to create Order */
     CreateOrder = 'CreateOrder',
-    /** Grants permission to Read Order */
+    /** Grants permission to read Order */
     ReadOrder = 'ReadOrder',
-    /** Grants permission to Update Order */
+    /** Grants permission to update Order */
     UpdateOrder = 'UpdateOrder',
-    /** Grants permission to Delete Order */
+    /** Grants permission to delete Order */
     DeleteOrder = 'DeleteOrder',
-    /** Grants permission to Create Promotion */
+    /** Grants permission to create Promotion */
     CreatePromotion = 'CreatePromotion',
-    /** Grants permission to Read Promotion */
+    /** Grants permission to read Promotion */
     ReadPromotion = 'ReadPromotion',
-    /** Grants permission to Update Promotion */
+    /** Grants permission to update Promotion */
     UpdatePromotion = 'UpdatePromotion',
-    /** Grants permission to Delete Promotion */
+    /** Grants permission to delete Promotion */
     DeletePromotion = 'DeletePromotion',
-    /** Grants permission to Create Settings */
+    /** Grants permission to create Settings */
     CreateSettings = 'CreateSettings',
-    /** Grants permission to Read Settings */
+    /** Grants permission to read Settings */
     ReadSettings = 'ReadSettings',
-    /** Grants permission to Update Settings */
+    /** Grants permission to update Settings */
     UpdateSettings = 'UpdateSettings',
-    /** Grants permission to Delete Settings */
+    /** Grants permission to delete Settings */
     DeleteSettings = 'DeleteSettings',
 }
 
@@ -3013,9 +3013,16 @@ export type OrderProcessState = {
     to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+    name: Scalars['String'];
+    description: Scalars['String'];
+    assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
     orderProcess: Array<OrderProcessState>;
     permittedAssetTypes: Array<Scalars['String']>;
+    permissions: Array<PermissionDefinition>;
     customFieldConfig: CustomFields;
 };
 

+ 32 - 24
packages/common/src/generated-shop-types.ts

@@ -367,53 +367,53 @@ export enum Permission {
     Owner = 'Owner',
     /** Public means any unauthenticated user may perform the operation */
     Public = 'Public',
-    /** Grants permission to Create Catalog */
+    /** Grants permission to create Catalog */
     CreateCatalog = 'CreateCatalog',
-    /** Grants permission to Read Catalog */
+    /** Grants permission to read Catalog */
     ReadCatalog = 'ReadCatalog',
-    /** Grants permission to Update Catalog */
+    /** Grants permission to update Catalog */
     UpdateCatalog = 'UpdateCatalog',
-    /** Grants permission to Delete Catalog */
+    /** Grants permission to delete Catalog */
     DeleteCatalog = 'DeleteCatalog',
-    /** Grants permission to Create Customer */
+    /** Grants permission to create Customer */
     CreateCustomer = 'CreateCustomer',
-    /** Grants permission to Read Customer */
+    /** Grants permission to read Customer */
     ReadCustomer = 'ReadCustomer',
-    /** Grants permission to Update Customer */
+    /** Grants permission to update Customer */
     UpdateCustomer = 'UpdateCustomer',
-    /** Grants permission to Delete Customer */
+    /** Grants permission to delete Customer */
     DeleteCustomer = 'DeleteCustomer',
-    /** Grants permission to Create Administrator */
+    /** Grants permission to create Administrator */
     CreateAdministrator = 'CreateAdministrator',
-    /** Grants permission to Read Administrator */
+    /** Grants permission to read Administrator */
     ReadAdministrator = 'ReadAdministrator',
-    /** Grants permission to Update Administrator */
+    /** Grants permission to update Administrator */
     UpdateAdministrator = 'UpdateAdministrator',
-    /** Grants permission to Delete Administrator */
+    /** Grants permission to delete Administrator */
     DeleteAdministrator = 'DeleteAdministrator',
-    /** Grants permission to Create Order */
+    /** Grants permission to create Order */
     CreateOrder = 'CreateOrder',
-    /** Grants permission to Read Order */
+    /** Grants permission to read Order */
     ReadOrder = 'ReadOrder',
-    /** Grants permission to Update Order */
+    /** Grants permission to update Order */
     UpdateOrder = 'UpdateOrder',
-    /** Grants permission to Delete Order */
+    /** Grants permission to delete Order */
     DeleteOrder = 'DeleteOrder',
-    /** Grants permission to Create Promotion */
+    /** Grants permission to create Promotion */
     CreatePromotion = 'CreatePromotion',
-    /** Grants permission to Read Promotion */
+    /** Grants permission to read Promotion */
     ReadPromotion = 'ReadPromotion',
-    /** Grants permission to Update Promotion */
+    /** Grants permission to update Promotion */
     UpdatePromotion = 'UpdatePromotion',
-    /** Grants permission to Delete Promotion */
+    /** Grants permission to delete Promotion */
     DeletePromotion = 'DeletePromotion',
-    /** Grants permission to Create Settings */
+    /** Grants permission to create Settings */
     CreateSettings = 'CreateSettings',
-    /** Grants permission to Read Settings */
+    /** Grants permission to read Settings */
     ReadSettings = 'ReadSettings',
-    /** Grants permission to Update Settings */
+    /** Grants permission to update Settings */
     UpdateSettings = 'UpdateSettings',
-    /** Grants permission to Delete Settings */
+    /** Grants permission to delete Settings */
     DeleteSettings = 'DeleteSettings',
 }
 
@@ -1935,10 +1935,18 @@ export type OrderProcessState = {
     to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+    __typename?: 'PermissionDefinition';
+    name: Scalars['String'];
+    description: Scalars['String'];
+    assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
     __typename?: 'ServerConfig';
     orderProcess: Array<OrderProcessState>;
     permittedAssetTypes: Array<Scalars['String']>;
+    permissions: Array<PermissionDefinition>;
     customFieldConfig: CustomFields;
 };
 

+ 32 - 24
packages/common/src/generated-types.ts

@@ -1966,53 +1966,53 @@ export enum Permission {
   Owner = 'Owner',
   /** Public means any unauthenticated user may perform the operation */
   Public = 'Public',
-  /** Grants permission to Create Catalog */
+  /** Grants permission to create Catalog */
   CreateCatalog = 'CreateCatalog',
-  /** Grants permission to Read Catalog */
+  /** Grants permission to read Catalog */
   ReadCatalog = 'ReadCatalog',
-  /** Grants permission to Update Catalog */
+  /** Grants permission to update Catalog */
   UpdateCatalog = 'UpdateCatalog',
-  /** Grants permission to Delete Catalog */
+  /** Grants permission to delete Catalog */
   DeleteCatalog = 'DeleteCatalog',
-  /** Grants permission to Create Customer */
+  /** Grants permission to create Customer */
   CreateCustomer = 'CreateCustomer',
-  /** Grants permission to Read Customer */
+  /** Grants permission to read Customer */
   ReadCustomer = 'ReadCustomer',
-  /** Grants permission to Update Customer */
+  /** Grants permission to update Customer */
   UpdateCustomer = 'UpdateCustomer',
-  /** Grants permission to Delete Customer */
+  /** Grants permission to delete Customer */
   DeleteCustomer = 'DeleteCustomer',
-  /** Grants permission to Create Administrator */
+  /** Grants permission to create Administrator */
   CreateAdministrator = 'CreateAdministrator',
-  /** Grants permission to Read Administrator */
+  /** Grants permission to read Administrator */
   ReadAdministrator = 'ReadAdministrator',
-  /** Grants permission to Update Administrator */
+  /** Grants permission to update Administrator */
   UpdateAdministrator = 'UpdateAdministrator',
-  /** Grants permission to Delete Administrator */
+  /** Grants permission to delete Administrator */
   DeleteAdministrator = 'DeleteAdministrator',
-  /** Grants permission to Create Order */
+  /** Grants permission to create Order */
   CreateOrder = 'CreateOrder',
-  /** Grants permission to Read Order */
+  /** Grants permission to read Order */
   ReadOrder = 'ReadOrder',
-  /** Grants permission to Update Order */
+  /** Grants permission to update Order */
   UpdateOrder = 'UpdateOrder',
-  /** Grants permission to Delete Order */
+  /** Grants permission to delete Order */
   DeleteOrder = 'DeleteOrder',
-  /** Grants permission to Create Promotion */
+  /** Grants permission to create Promotion */
   CreatePromotion = 'CreatePromotion',
-  /** Grants permission to Read Promotion */
+  /** Grants permission to read Promotion */
   ReadPromotion = 'ReadPromotion',
-  /** Grants permission to Update Promotion */
+  /** Grants permission to update Promotion */
   UpdatePromotion = 'UpdatePromotion',
-  /** Grants permission to Delete Promotion */
+  /** Grants permission to delete Promotion */
   DeletePromotion = 'DeletePromotion',
-  /** Grants permission to Create Settings */
+  /** Grants permission to create Settings */
   CreateSettings = 'CreateSettings',
-  /** Grants permission to Read Settings */
+  /** Grants permission to read Settings */
   ReadSettings = 'ReadSettings',
-  /** Grants permission to Update Settings */
+  /** Grants permission to update Settings */
   UpdateSettings = 'UpdateSettings',
-  /** Grants permission to Delete Settings */
+  /** Grants permission to delete Settings */
   DeleteSettings = 'DeleteSettings'
 }
 
@@ -3201,10 +3201,18 @@ export type OrderProcessState = {
   to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+  __typename?: 'PermissionDefinition';
+  name: Scalars['String'];
+  description: Scalars['String'];
+  assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
   __typename?: 'ServerConfig';
   orderProcess: Array<OrderProcessState>;
   permittedAssetTypes: Array<Scalars['String']>;
+  permissions: Array<PermissionDefinition>;
   customFieldConfig: CustomFields;
 };
 

+ 0 - 1
packages/core/e2e/__snapshots__/administrator.e2e-spec.ts.snap

@@ -18,7 +18,6 @@ Object {
         "permissions": Array [
           "Authenticated",
           "SuperAdmin",
-          "Public",
           "CreateCatalog",
           "ReadCatalog",
           "UpdateCatalog",

+ 4 - 2
packages/core/e2e/channel.e2e-spec.ts

@@ -10,7 +10,7 @@ import gql from 'graphql-tag';
 import path from 'path';
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
-import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
+import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
 
 import {
     AssignProductsToChannel,
@@ -140,7 +140,9 @@ describe('Channels', () => {
         expect(me!.channels.length).toBe(2);
 
         const secondChannelData = me!.channels.find(c => c.token === SECOND_CHANNEL_TOKEN);
-        const nonOwnerPermissions = Object.values(Permission).filter(p => p !== Permission.Owner);
+        const nonOwnerPermissions = Object.values(Permission).filter(
+            p => p !== Permission.Owner && p !== Permission.Public,
+        );
         expect(secondChannelData!.permissions).toEqual(nonOwnerPermissions);
     });
 

+ 8 - 0
packages/core/e2e/global-settings.e2e-spec.ts

@@ -69,6 +69,14 @@ describe('GlobalSettings resolver', () => {
         it('includes customFieldConfig', () => {
             expect(globalSettings.serverConfig.customFieldConfig.Customer).toEqual([{ name: 'age' }]);
         });
+
+        it('includes non-internal permission definitions', () => {
+            const permissionNames = globalSettings.serverConfig.permissions.map(p => p.name);
+            expect(permissionNames).toContain('CreateAdministrator');
+            expect(permissionNames).not.toContain('SuperAdmin');
+            expect(permissionNames).not.toContain('Owner');
+            expect(permissionNames).not.toContain('Authenticated');
+        });
     });
 
     describe('update', () => {

+ 5 - 0
packages/core/e2e/graphql/fragments.ts

@@ -525,6 +525,11 @@ export const GLOBAL_SETTINGS_FRAGMENT = gql`
                 to
             }
             permittedAssetTypes
+            permissions {
+                name
+                description
+                assignable
+            }
             customFieldConfig {
                 Customer {
                     ... on CustomField {

+ 47 - 36
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1811,53 +1811,53 @@ export enum Permission {
     Owner = 'Owner',
     /** Public means any unauthenticated user may perform the operation */
     Public = 'Public',
-    /** Grants permission to Create Catalog */
+    /** Grants permission to create Catalog */
     CreateCatalog = 'CreateCatalog',
-    /** Grants permission to Read Catalog */
+    /** Grants permission to read Catalog */
     ReadCatalog = 'ReadCatalog',
-    /** Grants permission to Update Catalog */
+    /** Grants permission to update Catalog */
     UpdateCatalog = 'UpdateCatalog',
-    /** Grants permission to Delete Catalog */
+    /** Grants permission to delete Catalog */
     DeleteCatalog = 'DeleteCatalog',
-    /** Grants permission to Create Customer */
+    /** Grants permission to create Customer */
     CreateCustomer = 'CreateCustomer',
-    /** Grants permission to Read Customer */
+    /** Grants permission to read Customer */
     ReadCustomer = 'ReadCustomer',
-    /** Grants permission to Update Customer */
+    /** Grants permission to update Customer */
     UpdateCustomer = 'UpdateCustomer',
-    /** Grants permission to Delete Customer */
+    /** Grants permission to delete Customer */
     DeleteCustomer = 'DeleteCustomer',
-    /** Grants permission to Create Administrator */
+    /** Grants permission to create Administrator */
     CreateAdministrator = 'CreateAdministrator',
-    /** Grants permission to Read Administrator */
+    /** Grants permission to read Administrator */
     ReadAdministrator = 'ReadAdministrator',
-    /** Grants permission to Update Administrator */
+    /** Grants permission to update Administrator */
     UpdateAdministrator = 'UpdateAdministrator',
-    /** Grants permission to Delete Administrator */
+    /** Grants permission to delete Administrator */
     DeleteAdministrator = 'DeleteAdministrator',
-    /** Grants permission to Create Order */
+    /** Grants permission to create Order */
     CreateOrder = 'CreateOrder',
-    /** Grants permission to Read Order */
+    /** Grants permission to read Order */
     ReadOrder = 'ReadOrder',
-    /** Grants permission to Update Order */
+    /** Grants permission to update Order */
     UpdateOrder = 'UpdateOrder',
-    /** Grants permission to Delete Order */
+    /** Grants permission to delete Order */
     DeleteOrder = 'DeleteOrder',
-    /** Grants permission to Create Promotion */
+    /** Grants permission to create Promotion */
     CreatePromotion = 'CreatePromotion',
-    /** Grants permission to Read Promotion */
+    /** Grants permission to read Promotion */
     ReadPromotion = 'ReadPromotion',
-    /** Grants permission to Update Promotion */
+    /** Grants permission to update Promotion */
     UpdatePromotion = 'UpdatePromotion',
-    /** Grants permission to Delete Promotion */
+    /** Grants permission to delete Promotion */
     DeletePromotion = 'DeletePromotion',
-    /** Grants permission to Create Settings */
+    /** Grants permission to create Settings */
     CreateSettings = 'CreateSettings',
-    /** Grants permission to Read Settings */
+    /** Grants permission to read Settings */
     ReadSettings = 'ReadSettings',
-    /** Grants permission to Update Settings */
+    /** Grants permission to update Settings */
     UpdateSettings = 'UpdateSettings',
-    /** Grants permission to Delete Settings */
+    /** Grants permission to delete Settings */
     DeleteSettings = 'DeleteSettings',
 }
 
@@ -3013,9 +3013,16 @@ export type OrderProcessState = {
     to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+    name: Scalars['String'];
+    description: Scalars['String'];
+    assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
     orderProcess: Array<OrderProcessState>;
     permittedAssetTypes: Array<Scalars['String']>;
+    permissions: Array<PermissionDefinition>;
     customFieldConfig: CustomFields;
 };
 
@@ -4619,6 +4626,7 @@ export type GlobalSettingsFragment = Pick<
 > & {
     serverConfig: Pick<ServerConfig, 'permittedAssetTypes'> & {
         orderProcess: Array<Pick<OrderProcessState, 'name' | 'to'>>;
+        permissions: Array<Pick<PermissionDefinition, 'name' | 'description' | 'assignable'>>;
         customFieldConfig: {
             Customer: Array<
                 | Pick<StringCustomFieldConfig, 'name'>
@@ -5134,6 +5142,12 @@ export type UpdateGlobalSettingsMutation = {
     updateGlobalSettings: GlobalSettingsFragment | Pick<ChannelDefaultLanguageError, 'errorCode' | 'message'>;
 };
 
+export type UpdateRoleMutationVariables = Exact<{
+    input: UpdateRoleInput;
+}>;
+
+export type UpdateRoleMutation = { updateRole: RoleFragment };
+
 export type UpdateOptionGroupMutationVariables = Exact<{
     input: UpdateProductOptionGroupInput;
 }>;
@@ -5398,12 +5412,6 @@ export type GetRoleQueryVariables = Exact<{
 
 export type GetRoleQuery = { role?: Maybe<RoleFragment> };
 
-export type UpdateRoleMutationVariables = Exact<{
-    input: UpdateRoleInput;
-}>;
-
-export type UpdateRoleMutation = { updateRole: RoleFragment };
-
 export type DeleteRoleMutationVariables = Exact<{
     id: Scalars['ID'];
 }>;
@@ -6476,6 +6484,9 @@ export namespace GlobalSettings {
     export type OrderProcess = NonNullable<
         NonNullable<NonNullable<GlobalSettingsFragment['serverConfig']>['orderProcess']>[number]
     >;
+    export type Permissions = NonNullable<
+        NonNullable<NonNullable<GlobalSettingsFragment['serverConfig']>['permissions']>[number]
+    >;
     export type CustomFieldConfig = NonNullable<
         NonNullable<GlobalSettingsFragment['serverConfig']>['customFieldConfig']
     >;
@@ -6972,6 +6983,12 @@ export namespace UpdateGlobalSettings {
     >;
 }
 
+export namespace UpdateRole {
+    export type Variables = UpdateRoleMutationVariables;
+    export type Mutation = UpdateRoleMutation;
+    export type UpdateRole = NonNullable<UpdateRoleMutation['updateRole']>;
+}
+
 export namespace UpdateOptionGroup {
     export type Variables = UpdateOptionGroupMutationVariables;
     export type Mutation = UpdateOptionGroupMutation;
@@ -7262,12 +7279,6 @@ export namespace GetRole {
     export type Role = NonNullable<GetRoleQuery['role']>;
 }
 
-export namespace UpdateRole {
-    export type Variables = UpdateRoleMutationVariables;
-    export type Mutation = UpdateRoleMutation;
-    export type UpdateRole = NonNullable<UpdateRoleMutation['updateRole']>;
-}
-
 export namespace DeleteRole {
     export type Variables = DeleteRoleMutationVariables;
     export type Mutation = DeleteRoleMutation;

+ 31 - 24
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -360,53 +360,53 @@ export enum Permission {
     Owner = 'Owner',
     /** Public means any unauthenticated user may perform the operation */
     Public = 'Public',
-    /** Grants permission to Create Catalog */
+    /** Grants permission to create Catalog */
     CreateCatalog = 'CreateCatalog',
-    /** Grants permission to Read Catalog */
+    /** Grants permission to read Catalog */
     ReadCatalog = 'ReadCatalog',
-    /** Grants permission to Update Catalog */
+    /** Grants permission to update Catalog */
     UpdateCatalog = 'UpdateCatalog',
-    /** Grants permission to Delete Catalog */
+    /** Grants permission to delete Catalog */
     DeleteCatalog = 'DeleteCatalog',
-    /** Grants permission to Create Customer */
+    /** Grants permission to create Customer */
     CreateCustomer = 'CreateCustomer',
-    /** Grants permission to Read Customer */
+    /** Grants permission to read Customer */
     ReadCustomer = 'ReadCustomer',
-    /** Grants permission to Update Customer */
+    /** Grants permission to update Customer */
     UpdateCustomer = 'UpdateCustomer',
-    /** Grants permission to Delete Customer */
+    /** Grants permission to delete Customer */
     DeleteCustomer = 'DeleteCustomer',
-    /** Grants permission to Create Administrator */
+    /** Grants permission to create Administrator */
     CreateAdministrator = 'CreateAdministrator',
-    /** Grants permission to Read Administrator */
+    /** Grants permission to read Administrator */
     ReadAdministrator = 'ReadAdministrator',
-    /** Grants permission to Update Administrator */
+    /** Grants permission to update Administrator */
     UpdateAdministrator = 'UpdateAdministrator',
-    /** Grants permission to Delete Administrator */
+    /** Grants permission to delete Administrator */
     DeleteAdministrator = 'DeleteAdministrator',
-    /** Grants permission to Create Order */
+    /** Grants permission to create Order */
     CreateOrder = 'CreateOrder',
-    /** Grants permission to Read Order */
+    /** Grants permission to read Order */
     ReadOrder = 'ReadOrder',
-    /** Grants permission to Update Order */
+    /** Grants permission to update Order */
     UpdateOrder = 'UpdateOrder',
-    /** Grants permission to Delete Order */
+    /** Grants permission to delete Order */
     DeleteOrder = 'DeleteOrder',
-    /** Grants permission to Create Promotion */
+    /** Grants permission to create Promotion */
     CreatePromotion = 'CreatePromotion',
-    /** Grants permission to Read Promotion */
+    /** Grants permission to read Promotion */
     ReadPromotion = 'ReadPromotion',
-    /** Grants permission to Update Promotion */
+    /** Grants permission to update Promotion */
     UpdatePromotion = 'UpdatePromotion',
-    /** Grants permission to Delete Promotion */
+    /** Grants permission to delete Promotion */
     DeletePromotion = 'DeletePromotion',
-    /** Grants permission to Create Settings */
+    /** Grants permission to create Settings */
     CreateSettings = 'CreateSettings',
-    /** Grants permission to Read Settings */
+    /** Grants permission to read Settings */
     ReadSettings = 'ReadSettings',
-    /** Grants permission to Update Settings */
+    /** Grants permission to update Settings */
     UpdateSettings = 'UpdateSettings',
-    /** Grants permission to Delete Settings */
+    /** Grants permission to delete Settings */
     DeleteSettings = 'DeleteSettings',
 }
 
@@ -1867,9 +1867,16 @@ export type OrderProcessState = {
     to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+    name: Scalars['String'];
+    description: Scalars['String'];
+    assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
     orderProcess: Array<OrderProcessState>;
     permittedAssetTypes: Array<Scalars['String']>;
+    permissions: Array<PermissionDefinition>;
     customFieldConfig: CustomFields;
 };
 

+ 124 - 79
packages/core/e2e/role.e2e-spec.ts

@@ -141,100 +141,145 @@ describe('Role resolver', () => {
         expect(result.role).toEqual(createdRole);
     });
 
-    it('updateRole', async () => {
-        const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
-            input: {
-                id: createdRole.id,
+    describe('updateRole', () => {
+        it('updates role', async () => {
+            const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                input: {
+                    id: createdRole.id,
+                    code: 'test-modified',
+                    description: 'test role modified',
+                    permissions: [
+                        Permission.ReadCustomer,
+                        Permission.UpdateCustomer,
+                        Permission.DeleteCustomer,
+                    ],
+                },
+            });
+
+            expect(omit(result.updateRole, ['channels'])).toEqual({
                 code: 'test-modified',
                 description: 'test role modified',
-                permissions: [Permission.ReadCustomer, Permission.UpdateCustomer, Permission.DeleteCustomer],
-            },
+                id: 'T_5',
+                permissions: [
+                    Permission.Authenticated,
+                    Permission.ReadCustomer,
+                    Permission.UpdateCustomer,
+                    Permission.DeleteCustomer,
+                ],
+            });
         });
 
-        expect(omit(result.updateRole, ['channels'])).toEqual({
-            code: 'test-modified',
-            description: 'test role modified',
-            id: 'T_5',
-            permissions: [
+        it('works with partial input', async () => {
+            const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                input: {
+                    id: createdRole.id,
+                    code: 'test-modified-again',
+                },
+            });
+
+            expect(result.updateRole.code).toBe('test-modified-again');
+            expect(result.updateRole.description).toBe('test role modified');
+            expect(result.updateRole.permissions).toEqual([
                 Permission.Authenticated,
                 Permission.ReadCustomer,
                 Permission.UpdateCustomer,
                 Permission.DeleteCustomer,
-            ],
+            ]);
         });
-    });
 
-    it('updateRole works with partial input', async () => {
-        const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
-            input: {
-                id: createdRole.id,
-                code: 'test-modified-again',
-            },
+        it('deduplicates permissions', async () => {
+            const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                input: {
+                    id: createdRole.id,
+                    permissions: [
+                        Permission.Authenticated,
+                        Permission.Authenticated,
+                        Permission.ReadCustomer,
+                        Permission.ReadCustomer,
+                    ],
+                },
+            });
+
+            expect(result.updateRole.permissions).toEqual([
+                Permission.Authenticated,
+                Permission.ReadCustomer,
+            ]);
         });
 
-        expect(result.updateRole.code).toBe('test-modified-again');
-        expect(result.updateRole.description).toBe('test role modified');
-        expect(result.updateRole.permissions).toEqual([
-            Permission.Authenticated,
-            Permission.ReadCustomer,
-            Permission.UpdateCustomer,
-            Permission.DeleteCustomer,
-        ]);
-    });
+        it(
+            'does not allow setting non-assignable permissions - Owner',
+            assertThrowsWithMessage(async () => {
+                await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                    input: {
+                        id: createdRole.id,
+                        permissions: [Permission.Owner],
+                    },
+                });
+            }, 'The permission "Owner" may not be assigned'),
+        );
 
-    it('updateRole deduplicates permissions', async () => {
-        const result = await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
-            input: {
-                id: createdRole.id,
-                permissions: [
-                    Permission.Authenticated,
-                    Permission.Authenticated,
-                    Permission.ReadCustomer,
-                    Permission.ReadCustomer,
-                ],
-            },
-        });
+        it(
+            'does not allow setting non-assignable permissions - Public',
+            assertThrowsWithMessage(async () => {
+                await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                    input: {
+                        id: createdRole.id,
+                        permissions: [Permission.Public],
+                    },
+                });
+            }, 'The permission "Public" may not be assigned'),
+        );
 
-        expect(result.updateRole.permissions).toEqual([Permission.Authenticated, Permission.ReadCustomer]);
-    });
+        it(
+            'does not allow setting SuperAdmin permission',
+            assertThrowsWithMessage(async () => {
+                await adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                    input: {
+                        id: createdRole.id,
+                        permissions: [Permission.SuperAdmin],
+                    },
+                });
+            }, 'The permission "SuperAdmin" may not be assigned'),
+        );
 
-    it(
-        'updateRole is not allowed for SuperAdmin role',
-        assertThrowsWithMessage(async () => {
-            const superAdminRole = defaultRoles.find(r => r.code === SUPER_ADMIN_ROLE_CODE);
-            if (!superAdminRole) {
-                fail(`Could not find SuperAdmin role`);
-                return;
-            }
-            return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
-                input: {
-                    id: superAdminRole.id,
-                    code: 'superadmin-modified',
-                    description: 'superadmin modified',
-                    permissions: [Permission.Authenticated],
-                },
-            });
-        }, `The role '${SUPER_ADMIN_ROLE_CODE}' cannot be modified`),
-    );
+        it(
+            'is not allowed for SuperAdmin role',
+            assertThrowsWithMessage(async () => {
+                const superAdminRole = defaultRoles.find(r => r.code === SUPER_ADMIN_ROLE_CODE);
+                if (!superAdminRole) {
+                    fail(`Could not find SuperAdmin role`);
+                    return;
+                }
+                return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                    input: {
+                        id: superAdminRole.id,
+                        code: 'superadmin-modified',
+                        description: 'superadmin modified',
+                        permissions: [Permission.Authenticated],
+                    },
+                });
+            }, `The role '${SUPER_ADMIN_ROLE_CODE}' cannot be modified`),
+        );
 
-    it(
-        'updateRole is not allowed for Customer role',
-        assertThrowsWithMessage(async () => {
-            const customerRole = defaultRoles.find(r => r.code === CUSTOMER_ROLE_CODE);
-            if (!customerRole) {
-                fail(`Could not find Customer role`);
-                return;
-            }
-            return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
-                input: {
-                    id: customerRole.id,
-                    code: 'customer-modified',
-                    description: 'customer modified',
-                    permissions: [Permission.Authenticated, Permission.DeleteAdministrator],
-                },
-            });
-        }, `The role '${CUSTOMER_ROLE_CODE}' cannot be modified`),
-    );
+        it(
+            'is not allowed for Customer role',
+            assertThrowsWithMessage(async () => {
+                const customerRole = defaultRoles.find(r => r.code === CUSTOMER_ROLE_CODE);
+                if (!customerRole) {
+                    fail(`Could not find Customer role`);
+                    return;
+                }
+                return adminClient.query<UpdateRole.Mutation, UpdateRole.Variables>(UPDATE_ROLE, {
+                    input: {
+                        id: customerRole.id,
+                        code: 'customer-modified',
+                        description: 'customer modified',
+                        permissions: [Permission.Authenticated, Permission.DeleteAdministrator],
+                    },
+                });
+            }, `The role '${CUSTOMER_ROLE_CODE}' cannot be modified`),
+        );
+    });
 
     it(
         'deleteRole is not allowed for Customer role',
@@ -300,7 +345,7 @@ describe('Role resolver', () => {
                 },
             });
 
-            secondChannel = createChannel;
+            secondChannel = createChannel as any;
         });
 
         it('createRole with specified channel', async () => {

+ 9 - 6
packages/core/src/api/resolvers/admin/global-settings.resolver.ts

@@ -1,14 +1,17 @@
 import { Args, Mutation, Query, ResolveField, Resolver } from '@nestjs/graphql';
 import {
+    CustomFields as GraphQLCustomFields,
     MutationUpdateGlobalSettingsArgs,
     OrderProcessState,
     Permission,
+    ServerConfig,
     UpdateGlobalSettingsResult,
 } from '@vendure/common/lib/generated-types';
 
 import { ErrorResultUnion } from '../../../common/error/error-result';
 import { UserInputError } from '../../../common/error/errors';
 import { ChannelDefaultLanguageError } from '../../../common/error/generated-graphql-admin-errors';
+import { getAllPermissionsMetadata } from '../../../common/permission-definition';
 import { ConfigService } from '../../../config/config.service';
 import { CustomFields } from '../../../config/custom-field/custom-field-types';
 import { GlobalSettings } from '../../../entity/global-settings/global-settings.entity';
@@ -39,11 +42,7 @@ export class GlobalSettingsResolver {
      * Exposes a subset of the VendureConfig which may be of use to clients.
      */
     @ResolveField()
-    serverConfig(): {
-        customFieldConfig: CustomFields;
-        orderProcess: OrderProcessState[];
-        permittedAssetTypes: string[];
-    } {
+    serverConfig(a: ServerConfig): ServerConfig {
         // Do not expose custom fields marked as "internal".
         const exposedCustomFieldConfig: CustomFields = {};
         for (const [entityType, customFields] of Object.entries(this.configService.customFields)) {
@@ -51,10 +50,14 @@ export class GlobalSettingsResolver {
                 .filter(c => !c.internal)
                 .map(c => ({ ...c, list: !!c.list as any }));
         }
+        const permissions = getAllPermissionsMetadata(
+            this.configService.authOptions.customPermissions,
+        ).filter(p => !p.internal);
         return {
-            customFieldConfig: exposedCustomFieldConfig,
+            customFieldConfig: exposedCustomFieldConfig as GraphQLCustomFields,
             orderProcess: this.orderService.getOrderProcessStates(),
             permittedAssetTypes: this.configService.assetOptions.permittedFileTypes,
+            permissions,
         };
     }
 

+ 7 - 0
packages/core/src/api/schema/type/global-settings.type.graphql

@@ -13,8 +13,15 @@ type OrderProcessState {
     to: [String!]!
 }
 
+type PermissionDefinition {
+    name: String!
+    description: String!
+    assignable: Boolean!
+}
+
 # Programatically extended by the addGraphQLCustomFields function
 type ServerConfig {
     orderProcess: [OrderProcessState!]!
     permittedAssetTypes: [String!]!
+    permissions: [PermissionDefinition!]!
 }

+ 7 - 0
packages/core/src/common/constants.ts

@@ -13,19 +13,26 @@ export const DEFAULT_PERMISSIONS: PermissionDefinition[] = [
     new PermissionDefinition({
         name: 'Authenticated',
         description: 'Authenticated means simply that the user is logged in',
+        assignable: true,
+        internal: true,
     }),
     new PermissionDefinition({
         name: 'SuperAdmin',
         description: 'SuperAdmin has unrestricted access to all operations',
+        assignable: true,
+        internal: true,
     }),
     new PermissionDefinition({
         name: 'Owner',
         description: `Owner means the user owns this entity, e.g. a Customer's own Order`,
         assignable: false,
+        internal: true,
     }),
     new PermissionDefinition({
         name: 'Public',
         description: `Public means any unauthenticated user may perform the operation`,
+        assignable: false,
+        internal: true,
     }),
     new CrudPermissionDefinition('Catalog'),
     new CrudPermissionDefinition('Customer'),

+ 10 - 1
packages/core/src/common/permission-definition.ts

@@ -29,6 +29,14 @@ export interface PermissionDefinitionConfig {
      * @default true
      */
     assignable?: boolean;
+    /**
+     * @description
+     * Internal permissions are not exposed via the API and are reserved for
+     * special use-cases such at the `Owner` or `Public` permissions.
+     *
+     * @default false
+     */
+    internal?: boolean;
 }
 
 /**
@@ -82,12 +90,13 @@ export class PermissionDefinition {
 
     /** @internal */
     getMetadata(): PermissionMetadata[] {
-        const { name, description, assignable } = this.config;
+        const { name, description, assignable, internal } = this.config;
         return [
             {
                 name,
                 description: description || `Grants permissions on ${name} operations`,
                 assignable: assignable ?? true,
+                internal: internal ?? false,
             },
         ];
     }

+ 1 - 1
packages/core/src/i18n/messages/en.json

@@ -29,7 +29,7 @@
     "no-search-plugin-configured": "No search plugin has been configured",
     "order-does-not-contain-line-with-id": "This order does not contain an OrderLine with the id { id }",
     "pending-identifier-missing": "Could not find the pending email address to update",
-    "permission-invalid": "The permission \"{ permission }\" is not valid",
+    "permission-invalid": "The permission \"{ permission }\" may not be assigned",
     "products-cannot-be-removed-from-default-channel": "Products cannot be removed from the default Channel",
     "product-id-or-slug-must-be-provided": "Either the Product id or slug must be provided",
     "product-id-slug-mismatch": "The provided id and slug refer to different Products",

+ 6 - 9
packages/core/src/service/services/role.service.ts

@@ -199,9 +199,11 @@ export class RoleService {
             return;
         }
         const { customPermissions } = this.configService.authOptions;
-        const allPermissions = getAllPermissionsMetadata(customPermissions).map(p => p.name as Permission);
+        const allAssignablePermissions = getAllPermissionsMetadata(customPermissions)
+            .filter(p => p.assignable)
+            .map(p => p.name as Permission);
         for (const permission of permissions) {
-            if (!allPermissions.includes(permission)) {
+            if (!allAssignablePermissions.includes(permission) || permission === Permission.SuperAdmin) {
                 throw new UserInputError('error.permission-invalid', { permission });
             }
         }
@@ -223,13 +225,8 @@ export class RoleService {
             .map(p => p.name as Permission);
         try {
             const superAdminRole = await this.getSuperAdminRole();
-            const hasAllPermissions = assignablePermissions.every(permission =>
-                superAdminRole.permissions.includes(permission),
-            );
-            if (!hasAllPermissions) {
-                superAdminRole.permissions = assignablePermissions;
-                await this.connection.getRepository(Role).save(superAdminRole, { reload: false });
-            }
+            superAdminRole.permissions = assignablePermissions;
+            await this.connection.getRepository(Role).save(superAdminRole, { reload: false });
         } catch (err) {
             await this.createRoleForChannels(
                 RequestContext.empty(),

+ 31 - 24
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -1811,53 +1811,53 @@ export enum Permission {
     Owner = 'Owner',
     /** Public means any unauthenticated user may perform the operation */
     Public = 'Public',
-    /** Grants permission to Create Catalog */
+    /** Grants permission to create Catalog */
     CreateCatalog = 'CreateCatalog',
-    /** Grants permission to Read Catalog */
+    /** Grants permission to read Catalog */
     ReadCatalog = 'ReadCatalog',
-    /** Grants permission to Update Catalog */
+    /** Grants permission to update Catalog */
     UpdateCatalog = 'UpdateCatalog',
-    /** Grants permission to Delete Catalog */
+    /** Grants permission to delete Catalog */
     DeleteCatalog = 'DeleteCatalog',
-    /** Grants permission to Create Customer */
+    /** Grants permission to create Customer */
     CreateCustomer = 'CreateCustomer',
-    /** Grants permission to Read Customer */
+    /** Grants permission to read Customer */
     ReadCustomer = 'ReadCustomer',
-    /** Grants permission to Update Customer */
+    /** Grants permission to update Customer */
     UpdateCustomer = 'UpdateCustomer',
-    /** Grants permission to Delete Customer */
+    /** Grants permission to delete Customer */
     DeleteCustomer = 'DeleteCustomer',
-    /** Grants permission to Create Administrator */
+    /** Grants permission to create Administrator */
     CreateAdministrator = 'CreateAdministrator',
-    /** Grants permission to Read Administrator */
+    /** Grants permission to read Administrator */
     ReadAdministrator = 'ReadAdministrator',
-    /** Grants permission to Update Administrator */
+    /** Grants permission to update Administrator */
     UpdateAdministrator = 'UpdateAdministrator',
-    /** Grants permission to Delete Administrator */
+    /** Grants permission to delete Administrator */
     DeleteAdministrator = 'DeleteAdministrator',
-    /** Grants permission to Create Order */
+    /** Grants permission to create Order */
     CreateOrder = 'CreateOrder',
-    /** Grants permission to Read Order */
+    /** Grants permission to read Order */
     ReadOrder = 'ReadOrder',
-    /** Grants permission to Update Order */
+    /** Grants permission to update Order */
     UpdateOrder = 'UpdateOrder',
-    /** Grants permission to Delete Order */
+    /** Grants permission to delete Order */
     DeleteOrder = 'DeleteOrder',
-    /** Grants permission to Create Promotion */
+    /** Grants permission to create Promotion */
     CreatePromotion = 'CreatePromotion',
-    /** Grants permission to Read Promotion */
+    /** Grants permission to read Promotion */
     ReadPromotion = 'ReadPromotion',
-    /** Grants permission to Update Promotion */
+    /** Grants permission to update Promotion */
     UpdatePromotion = 'UpdatePromotion',
-    /** Grants permission to Delete Promotion */
+    /** Grants permission to delete Promotion */
     DeletePromotion = 'DeletePromotion',
-    /** Grants permission to Create Settings */
+    /** Grants permission to create Settings */
     CreateSettings = 'CreateSettings',
-    /** Grants permission to Read Settings */
+    /** Grants permission to read Settings */
     ReadSettings = 'ReadSettings',
-    /** Grants permission to Update Settings */
+    /** Grants permission to update Settings */
     UpdateSettings = 'UpdateSettings',
-    /** Grants permission to Delete Settings */
+    /** Grants permission to delete Settings */
     DeleteSettings = 'DeleteSettings',
 }
 
@@ -3013,9 +3013,16 @@ export type OrderProcessState = {
     to: Array<Scalars['String']>;
 };
 
+export type PermissionDefinition = {
+    name: Scalars['String'];
+    description: Scalars['String'];
+    assignable: Scalars['Boolean'];
+};
+
 export type ServerConfig = {
     orderProcess: Array<OrderProcessState>;
     permittedAssetTypes: Array<Scalars['String']>;
+    permissions: Array<PermissionDefinition>;
     customFieldConfig: CustomFields;
 };
 

File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff