Ver código fonte

feat(core): Allow custom Permissions to be defined

Relates to #450. This commit changes the internal architecture of
Permission definition from static SDL-based to dynamic TypeScript.
Michael Bromley 5 anos atrás
pai
commit
1baeedf557

+ 67 - 43
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -1981,6 +1981,73 @@ export enum DeletionResult {
   NOT_DELETED = 'NOT_DELETED'
   NOT_DELETED = 'NOT_DELETED'
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ * 
+ * @docsCategory common
+ */
+export enum Permission {
+  /** Authenticated means simply that the user is logged in */
+  Authenticated = 'Authenticated',
+  /** Grants permission to Create Administrator */
+  CreateAdministrator = 'CreateAdministrator',
+  /** Grants permission to Create Catalog */
+  CreateCatalog = 'CreateCatalog',
+  /** Grants permission to Create Customer */
+  CreateCustomer = 'CreateCustomer',
+  /** Grants permission to Create Order */
+  CreateOrder = 'CreateOrder',
+  /** Grants permission to Create Promotion */
+  CreatePromotion = 'CreatePromotion',
+  /** Grants permission to Create Settings */
+  CreateSettings = 'CreateSettings',
+  /** Grants permission to Delete Administrator */
+  DeleteAdministrator = 'DeleteAdministrator',
+  /** Grants permission to Delete Catalog */
+  DeleteCatalog = 'DeleteCatalog',
+  /** Grants permission to Delete Customer */
+  DeleteCustomer = 'DeleteCustomer',
+  /** Grants permission to Delete Order */
+  DeleteOrder = 'DeleteOrder',
+  /** Grants permission to Delete Promotion */
+  DeletePromotion = 'DeletePromotion',
+  /** 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 */
+  ReadAdministrator = 'ReadAdministrator',
+  /** Grants permission to Read Catalog */
+  ReadCatalog = 'ReadCatalog',
+  /** Grants permission to Read Customer */
+  ReadCustomer = 'ReadCustomer',
+  /** Grants permission to Read Order */
+  ReadOrder = 'ReadOrder',
+  /** Grants permission to Read Promotion */
+  ReadPromotion = 'ReadPromotion',
+  /** Grants permission to Read Settings */
+  ReadSettings = 'ReadSettings',
+  /** SuperAdmin has unrestricted access to all operations */
+  SuperAdmin = 'SuperAdmin',
+  /** Grants permission to Update Administrator */
+  UpdateAdministrator = 'UpdateAdministrator',
+  /** Grants permission to Update Catalog */
+  UpdateCatalog = 'UpdateCatalog',
+  /** Grants permission to Update Customer */
+  UpdateCustomer = 'UpdateCustomer',
+  /** Grants permission to Update Order */
+  UpdateOrder = 'UpdateOrder',
+  /** Grants permission to Update Promotion */
+  UpdatePromotion = 'UpdatePromotion',
+  /** Grants permission to Update Settings */
+  UpdateSettings = 'UpdateSettings'
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
   __typename?: 'DeletionResponse';
   __typename?: 'DeletionResponse';
   result: DeletionResult;
   result: DeletionResult;
@@ -2935,49 +3002,6 @@ export enum LanguageCode {
   zu = 'zu'
   zu = 'zu'
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- * 
- * @docsCategory common
- */
-export enum Permission {
-  /**  The Authenticated role means simply that the user is logged in  */
-  Authenticated = 'Authenticated',
-  CreateAdministrator = 'CreateAdministrator',
-  CreateCatalog = 'CreateCatalog',
-  CreateCustomer = 'CreateCustomer',
-  CreateOrder = 'CreateOrder',
-  CreatePromotion = 'CreatePromotion',
-  CreateSettings = 'CreateSettings',
-  DeleteAdministrator = 'DeleteAdministrator',
-  DeleteCatalog = 'DeleteCatalog',
-  DeleteCustomer = 'DeleteCustomer',
-  DeleteOrder = 'DeleteOrder',
-  DeletePromotion = 'DeletePromotion',
-  DeleteSettings = 'DeleteSettings',
-  /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-  Owner = 'Owner',
-  /**  Public means any unauthenticated user may perform the operation  */
-  Public = 'Public',
-  ReadAdministrator = 'ReadAdministrator',
-  ReadCatalog = 'ReadCatalog',
-  ReadCustomer = 'ReadCustomer',
-  ReadOrder = 'ReadOrder',
-  ReadPromotion = 'ReadPromotion',
-  ReadSettings = 'ReadSettings',
-  /**  SuperAdmin can perform the most sensitive tasks */
-  SuperAdmin = 'SuperAdmin',
-  UpdateAdministrator = 'UpdateAdministrator',
-  UpdateCatalog = 'UpdateCatalog',
-  UpdateCustomer = 'UpdateCustomer',
-  UpdateOrder = 'UpdateOrder',
-  UpdatePromotion = 'UpdatePromotion',
-  UpdateSettings = 'UpdateSettings'
-}
-
 export type Address = Node & {
 export type Address = Node & {
   __typename?: 'Address';
   __typename?: 'Address';
   id: Scalars['ID'];
   id: Scalars['ID'];

+ 1 - 0
packages/admin-ui/src/lib/core/src/public_api.ts

@@ -120,6 +120,7 @@ export * from './shared/components/form-field/form-field-control.directive';
 export * from './shared/components/form-field/form-field.component';
 export * from './shared/components/form-field/form-field.component';
 export * from './shared/components/form-item/form-item.component';
 export * from './shared/components/form-item/form-item.component';
 export * from './shared/components/formatted-address/formatted-address.component';
 export * from './shared/components/formatted-address/formatted-address.component';
+export * from './shared/components/help-tooltip/help-tooltip.component';
 export * from './shared/components/history-entry-detail/history-entry-detail.component';
 export * from './shared/components/history-entry-detail/history-entry-detail.component';
 export * from './shared/components/items-per-page-controls/items-per-page-controls.component';
 export * from './shared/components/items-per-page-controls/items-per-page-controls.component';
 export * from './shared/components/labeled-data/labeled-data.component';
 export * from './shared/components/labeled-data/labeled-data.component';

+ 66 - 43
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -1795,6 +1795,72 @@ export enum DeletionResult {
     NOT_DELETED = 'NOT_DELETED',
     NOT_DELETED = 'NOT_DELETED',
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ *
+ * @docsCategory common
+ */
+export enum Permission {
+    /** Authenticated means simply that the user is logged in */
+    Authenticated = 'Authenticated',
+    /** SuperAdmin has unrestricted access to all operations */
+    SuperAdmin = 'SuperAdmin',
+    /** Owner means the user owns this entity, e.g. a Customer's own Order */
+    Owner = 'Owner',
+    /** Public means any unauthenticated user may perform the operation */
+    Public = 'Public',
+    /** Grants permission to Create Catalog */
+    CreateCatalog = 'CreateCatalog',
+    /** Grants permission to Read Catalog */
+    ReadCatalog = 'ReadCatalog',
+    /** Grants permission to Update Catalog */
+    UpdateCatalog = 'UpdateCatalog',
+    /** Grants permission to Delete Catalog */
+    DeleteCatalog = 'DeleteCatalog',
+    /** Grants permission to Create Customer */
+    CreateCustomer = 'CreateCustomer',
+    /** Grants permission to Read Customer */
+    ReadCustomer = 'ReadCustomer',
+    /** Grants permission to Update Customer */
+    UpdateCustomer = 'UpdateCustomer',
+    /** Grants permission to Delete Customer */
+    DeleteCustomer = 'DeleteCustomer',
+    /** Grants permission to Create Administrator */
+    CreateAdministrator = 'CreateAdministrator',
+    /** Grants permission to Read Administrator */
+    ReadAdministrator = 'ReadAdministrator',
+    /** Grants permission to Update Administrator */
+    UpdateAdministrator = 'UpdateAdministrator',
+    /** Grants permission to Delete Administrator */
+    DeleteAdministrator = 'DeleteAdministrator',
+    /** Grants permission to Create Order */
+    CreateOrder = 'CreateOrder',
+    /** Grants permission to Read Order */
+    ReadOrder = 'ReadOrder',
+    /** Grants permission to Update Order */
+    UpdateOrder = 'UpdateOrder',
+    /** Grants permission to Delete Order */
+    DeleteOrder = 'DeleteOrder',
+    /** Grants permission to Create Promotion */
+    CreatePromotion = 'CreatePromotion',
+    /** Grants permission to Read Promotion */
+    ReadPromotion = 'ReadPromotion',
+    /** Grants permission to Update Promotion */
+    UpdatePromotion = 'UpdatePromotion',
+    /** Grants permission to Delete Promotion */
+    DeletePromotion = 'DeletePromotion',
+    /** Grants permission to Create Settings */
+    CreateSettings = 'CreateSettings',
+    /** Grants permission to Read Settings */
+    ReadSettings = 'ReadSettings',
+    /** Grants permission to Update Settings */
+    UpdateSettings = 'UpdateSettings',
+    /** Grants permission to Delete Settings */
+    DeleteSettings = 'DeleteSettings',
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
     result: DeletionResult;
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
     message?: Maybe<Scalars['String']>;
@@ -2741,49 +2807,6 @@ export enum LanguageCode {
     zu = 'zu',
     zu = 'zu',
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- *
- * @docsCategory common
- */
-export enum Permission {
-    /**  The Authenticated role means simply that the user is logged in  */
-    Authenticated = 'Authenticated',
-    /**  SuperAdmin can perform the most sensitive tasks */
-    SuperAdmin = 'SuperAdmin',
-    /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-    Owner = 'Owner',
-    /**  Public means any unauthenticated user may perform the operation  */
-    Public = 'Public',
-    CreateCatalog = 'CreateCatalog',
-    ReadCatalog = 'ReadCatalog',
-    UpdateCatalog = 'UpdateCatalog',
-    DeleteCatalog = 'DeleteCatalog',
-    CreateCustomer = 'CreateCustomer',
-    ReadCustomer = 'ReadCustomer',
-    UpdateCustomer = 'UpdateCustomer',
-    DeleteCustomer = 'DeleteCustomer',
-    CreateAdministrator = 'CreateAdministrator',
-    ReadAdministrator = 'ReadAdministrator',
-    UpdateAdministrator = 'UpdateAdministrator',
-    DeleteAdministrator = 'DeleteAdministrator',
-    CreateOrder = 'CreateOrder',
-    ReadOrder = 'ReadOrder',
-    UpdateOrder = 'UpdateOrder',
-    DeleteOrder = 'DeleteOrder',
-    CreatePromotion = 'CreatePromotion',
-    ReadPromotion = 'ReadPromotion',
-    UpdatePromotion = 'UpdatePromotion',
-    DeletePromotion = 'DeletePromotion',
-    CreateSettings = 'CreateSettings',
-    ReadSettings = 'ReadSettings',
-    UpdateSettings = 'UpdateSettings',
-    DeleteSettings = 'DeleteSettings',
-}
-
 export type Address = Node & {
 export type Address = Node & {
     id: Scalars['ID'];
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     createdAt: Scalars['DateTime'];

+ 66 - 43
packages/common/src/generated-shop-types.ts

@@ -351,6 +351,72 @@ export enum DeletionResult {
     NOT_DELETED = 'NOT_DELETED',
     NOT_DELETED = 'NOT_DELETED',
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ *
+ * @docsCategory common
+ */
+export enum Permission {
+    /** Authenticated means simply that the user is logged in */
+    Authenticated = 'Authenticated',
+    /** SuperAdmin has unrestricted access to all operations */
+    SuperAdmin = 'SuperAdmin',
+    /** Owner means the user owns this entity, e.g. a Customer's own Order */
+    Owner = 'Owner',
+    /** Public means any unauthenticated user may perform the operation */
+    Public = 'Public',
+    /** Grants permission to Create Catalog */
+    CreateCatalog = 'CreateCatalog',
+    /** Grants permission to Read Catalog */
+    ReadCatalog = 'ReadCatalog',
+    /** Grants permission to Update Catalog */
+    UpdateCatalog = 'UpdateCatalog',
+    /** Grants permission to Delete Catalog */
+    DeleteCatalog = 'DeleteCatalog',
+    /** Grants permission to Create Customer */
+    CreateCustomer = 'CreateCustomer',
+    /** Grants permission to Read Customer */
+    ReadCustomer = 'ReadCustomer',
+    /** Grants permission to Update Customer */
+    UpdateCustomer = 'UpdateCustomer',
+    /** Grants permission to Delete Customer */
+    DeleteCustomer = 'DeleteCustomer',
+    /** Grants permission to Create Administrator */
+    CreateAdministrator = 'CreateAdministrator',
+    /** Grants permission to Read Administrator */
+    ReadAdministrator = 'ReadAdministrator',
+    /** Grants permission to Update Administrator */
+    UpdateAdministrator = 'UpdateAdministrator',
+    /** Grants permission to Delete Administrator */
+    DeleteAdministrator = 'DeleteAdministrator',
+    /** Grants permission to Create Order */
+    CreateOrder = 'CreateOrder',
+    /** Grants permission to Read Order */
+    ReadOrder = 'ReadOrder',
+    /** Grants permission to Update Order */
+    UpdateOrder = 'UpdateOrder',
+    /** Grants permission to Delete Order */
+    DeleteOrder = 'DeleteOrder',
+    /** Grants permission to Create Promotion */
+    CreatePromotion = 'CreatePromotion',
+    /** Grants permission to Read Promotion */
+    ReadPromotion = 'ReadPromotion',
+    /** Grants permission to Update Promotion */
+    UpdatePromotion = 'UpdatePromotion',
+    /** Grants permission to Delete Promotion */
+    DeletePromotion = 'DeletePromotion',
+    /** Grants permission to Create Settings */
+    CreateSettings = 'CreateSettings',
+    /** Grants permission to Read Settings */
+    ReadSettings = 'ReadSettings',
+    /** Grants permission to Update Settings */
+    UpdateSettings = 'UpdateSettings',
+    /** Grants permission to Delete Settings */
+    DeleteSettings = 'DeleteSettings',
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
     __typename?: 'DeletionResponse';
     __typename?: 'DeletionResponse';
     result: DeletionResult;
     result: DeletionResult;
@@ -1312,49 +1378,6 @@ export enum LanguageCode {
     zu = 'zu',
     zu = 'zu',
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- *
- * @docsCategory common
- */
-export enum Permission {
-    /**  The Authenticated role means simply that the user is logged in  */
-    Authenticated = 'Authenticated',
-    /**  SuperAdmin can perform the most sensitive tasks */
-    SuperAdmin = 'SuperAdmin',
-    /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-    Owner = 'Owner',
-    /**  Public means any unauthenticated user may perform the operation  */
-    Public = 'Public',
-    CreateCatalog = 'CreateCatalog',
-    ReadCatalog = 'ReadCatalog',
-    UpdateCatalog = 'UpdateCatalog',
-    DeleteCatalog = 'DeleteCatalog',
-    CreateCustomer = 'CreateCustomer',
-    ReadCustomer = 'ReadCustomer',
-    UpdateCustomer = 'UpdateCustomer',
-    DeleteCustomer = 'DeleteCustomer',
-    CreateAdministrator = 'CreateAdministrator',
-    ReadAdministrator = 'ReadAdministrator',
-    UpdateAdministrator = 'UpdateAdministrator',
-    DeleteAdministrator = 'DeleteAdministrator',
-    CreateOrder = 'CreateOrder',
-    ReadOrder = 'ReadOrder',
-    UpdateOrder = 'UpdateOrder',
-    DeleteOrder = 'DeleteOrder',
-    CreatePromotion = 'CreatePromotion',
-    ReadPromotion = 'ReadPromotion',
-    UpdatePromotion = 'UpdatePromotion',
-    DeletePromotion = 'DeletePromotion',
-    CreateSettings = 'CreateSettings',
-    ReadSettings = 'ReadSettings',
-    UpdateSettings = 'UpdateSettings',
-    DeleteSettings = 'DeleteSettings',
-}
-
 export type RegisterCustomerInput = {
 export type RegisterCustomerInput = {
     emailAddress: Scalars['String'];
     emailAddress: Scalars['String'];
     title?: Maybe<Scalars['String']>;
     title?: Maybe<Scalars['String']>;

+ 66 - 43
packages/common/src/generated-types.ts

@@ -1950,6 +1950,72 @@ export enum DeletionResult {
   NOT_DELETED = 'NOT_DELETED'
   NOT_DELETED = 'NOT_DELETED'
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ * 
+ * @docsCategory common
+ */
+export enum Permission {
+  /** Authenticated means simply that the user is logged in */
+  Authenticated = 'Authenticated',
+  /** SuperAdmin has unrestricted access to all operations */
+  SuperAdmin = 'SuperAdmin',
+  /** Owner means the user owns this entity, e.g. a Customer's own Order */
+  Owner = 'Owner',
+  /** Public means any unauthenticated user may perform the operation */
+  Public = 'Public',
+  /** Grants permission to Create Catalog */
+  CreateCatalog = 'CreateCatalog',
+  /** Grants permission to Read Catalog */
+  ReadCatalog = 'ReadCatalog',
+  /** Grants permission to Update Catalog */
+  UpdateCatalog = 'UpdateCatalog',
+  /** Grants permission to Delete Catalog */
+  DeleteCatalog = 'DeleteCatalog',
+  /** Grants permission to Create Customer */
+  CreateCustomer = 'CreateCustomer',
+  /** Grants permission to Read Customer */
+  ReadCustomer = 'ReadCustomer',
+  /** Grants permission to Update Customer */
+  UpdateCustomer = 'UpdateCustomer',
+  /** Grants permission to Delete Customer */
+  DeleteCustomer = 'DeleteCustomer',
+  /** Grants permission to Create Administrator */
+  CreateAdministrator = 'CreateAdministrator',
+  /** Grants permission to Read Administrator */
+  ReadAdministrator = 'ReadAdministrator',
+  /** Grants permission to Update Administrator */
+  UpdateAdministrator = 'UpdateAdministrator',
+  /** Grants permission to Delete Administrator */
+  DeleteAdministrator = 'DeleteAdministrator',
+  /** Grants permission to Create Order */
+  CreateOrder = 'CreateOrder',
+  /** Grants permission to Read Order */
+  ReadOrder = 'ReadOrder',
+  /** Grants permission to Update Order */
+  UpdateOrder = 'UpdateOrder',
+  /** Grants permission to Delete Order */
+  DeleteOrder = 'DeleteOrder',
+  /** Grants permission to Create Promotion */
+  CreatePromotion = 'CreatePromotion',
+  /** Grants permission to Read Promotion */
+  ReadPromotion = 'ReadPromotion',
+  /** Grants permission to Update Promotion */
+  UpdatePromotion = 'UpdatePromotion',
+  /** Grants permission to Delete Promotion */
+  DeletePromotion = 'DeletePromotion',
+  /** Grants permission to Create Settings */
+  CreateSettings = 'CreateSettings',
+  /** Grants permission to Read Settings */
+  ReadSettings = 'ReadSettings',
+  /** Grants permission to Update Settings */
+  UpdateSettings = 'UpdateSettings',
+  /** Grants permission to Delete Settings */
+  DeleteSettings = 'DeleteSettings'
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
   __typename?: 'DeletionResponse';
   __typename?: 'DeletionResponse';
   result: DeletionResult;
   result: DeletionResult;
@@ -2904,49 +2970,6 @@ export enum LanguageCode {
   zu = 'zu'
   zu = 'zu'
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- * 
- * @docsCategory common
- */
-export enum Permission {
-  /**  The Authenticated role means simply that the user is logged in  */
-  Authenticated = 'Authenticated',
-  /**  SuperAdmin can perform the most sensitive tasks */
-  SuperAdmin = 'SuperAdmin',
-  /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-  Owner = 'Owner',
-  /**  Public means any unauthenticated user may perform the operation  */
-  Public = 'Public',
-  CreateCatalog = 'CreateCatalog',
-  ReadCatalog = 'ReadCatalog',
-  UpdateCatalog = 'UpdateCatalog',
-  DeleteCatalog = 'DeleteCatalog',
-  CreateCustomer = 'CreateCustomer',
-  ReadCustomer = 'ReadCustomer',
-  UpdateCustomer = 'UpdateCustomer',
-  DeleteCustomer = 'DeleteCustomer',
-  CreateAdministrator = 'CreateAdministrator',
-  ReadAdministrator = 'ReadAdministrator',
-  UpdateAdministrator = 'UpdateAdministrator',
-  DeleteAdministrator = 'DeleteAdministrator',
-  CreateOrder = 'CreateOrder',
-  ReadOrder = 'ReadOrder',
-  UpdateOrder = 'UpdateOrder',
-  DeleteOrder = 'DeleteOrder',
-  CreatePromotion = 'CreatePromotion',
-  ReadPromotion = 'ReadPromotion',
-  UpdatePromotion = 'UpdatePromotion',
-  DeletePromotion = 'DeletePromotion',
-  CreateSettings = 'CreateSettings',
-  ReadSettings = 'ReadSettings',
-  UpdateSettings = 'UpdateSettings',
-  DeleteSettings = 'DeleteSettings'
-}
-
 export type Address = Node & {
 export type Address = Node & {
   __typename?: 'Address';
   __typename?: 'Address';
   id: Scalars['ID'];
   id: Scalars['ID'];

+ 66 - 43
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1795,6 +1795,72 @@ export enum DeletionResult {
     NOT_DELETED = 'NOT_DELETED',
     NOT_DELETED = 'NOT_DELETED',
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ *
+ * @docsCategory common
+ */
+export enum Permission {
+    /** Authenticated means simply that the user is logged in */
+    Authenticated = 'Authenticated',
+    /** SuperAdmin has unrestricted access to all operations */
+    SuperAdmin = 'SuperAdmin',
+    /** Owner means the user owns this entity, e.g. a Customer's own Order */
+    Owner = 'Owner',
+    /** Public means any unauthenticated user may perform the operation */
+    Public = 'Public',
+    /** Grants permission to Create Catalog */
+    CreateCatalog = 'CreateCatalog',
+    /** Grants permission to Read Catalog */
+    ReadCatalog = 'ReadCatalog',
+    /** Grants permission to Update Catalog */
+    UpdateCatalog = 'UpdateCatalog',
+    /** Grants permission to Delete Catalog */
+    DeleteCatalog = 'DeleteCatalog',
+    /** Grants permission to Create Customer */
+    CreateCustomer = 'CreateCustomer',
+    /** Grants permission to Read Customer */
+    ReadCustomer = 'ReadCustomer',
+    /** Grants permission to Update Customer */
+    UpdateCustomer = 'UpdateCustomer',
+    /** Grants permission to Delete Customer */
+    DeleteCustomer = 'DeleteCustomer',
+    /** Grants permission to Create Administrator */
+    CreateAdministrator = 'CreateAdministrator',
+    /** Grants permission to Read Administrator */
+    ReadAdministrator = 'ReadAdministrator',
+    /** Grants permission to Update Administrator */
+    UpdateAdministrator = 'UpdateAdministrator',
+    /** Grants permission to Delete Administrator */
+    DeleteAdministrator = 'DeleteAdministrator',
+    /** Grants permission to Create Order */
+    CreateOrder = 'CreateOrder',
+    /** Grants permission to Read Order */
+    ReadOrder = 'ReadOrder',
+    /** Grants permission to Update Order */
+    UpdateOrder = 'UpdateOrder',
+    /** Grants permission to Delete Order */
+    DeleteOrder = 'DeleteOrder',
+    /** Grants permission to Create Promotion */
+    CreatePromotion = 'CreatePromotion',
+    /** Grants permission to Read Promotion */
+    ReadPromotion = 'ReadPromotion',
+    /** Grants permission to Update Promotion */
+    UpdatePromotion = 'UpdatePromotion',
+    /** Grants permission to Delete Promotion */
+    DeletePromotion = 'DeletePromotion',
+    /** Grants permission to Create Settings */
+    CreateSettings = 'CreateSettings',
+    /** Grants permission to Read Settings */
+    ReadSettings = 'ReadSettings',
+    /** Grants permission to Update Settings */
+    UpdateSettings = 'UpdateSettings',
+    /** Grants permission to Delete Settings */
+    DeleteSettings = 'DeleteSettings',
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
     result: DeletionResult;
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
     message?: Maybe<Scalars['String']>;
@@ -2741,49 +2807,6 @@ export enum LanguageCode {
     zu = 'zu',
     zu = 'zu',
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- *
- * @docsCategory common
- */
-export enum Permission {
-    /**  The Authenticated role means simply that the user is logged in  */
-    Authenticated = 'Authenticated',
-    /**  SuperAdmin can perform the most sensitive tasks */
-    SuperAdmin = 'SuperAdmin',
-    /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-    Owner = 'Owner',
-    /**  Public means any unauthenticated user may perform the operation  */
-    Public = 'Public',
-    CreateCatalog = 'CreateCatalog',
-    ReadCatalog = 'ReadCatalog',
-    UpdateCatalog = 'UpdateCatalog',
-    DeleteCatalog = 'DeleteCatalog',
-    CreateCustomer = 'CreateCustomer',
-    ReadCustomer = 'ReadCustomer',
-    UpdateCustomer = 'UpdateCustomer',
-    DeleteCustomer = 'DeleteCustomer',
-    CreateAdministrator = 'CreateAdministrator',
-    ReadAdministrator = 'ReadAdministrator',
-    UpdateAdministrator = 'UpdateAdministrator',
-    DeleteAdministrator = 'DeleteAdministrator',
-    CreateOrder = 'CreateOrder',
-    ReadOrder = 'ReadOrder',
-    UpdateOrder = 'UpdateOrder',
-    DeleteOrder = 'DeleteOrder',
-    CreatePromotion = 'CreatePromotion',
-    ReadPromotion = 'ReadPromotion',
-    UpdatePromotion = 'UpdatePromotion',
-    DeletePromotion = 'DeletePromotion',
-    CreateSettings = 'CreateSettings',
-    ReadSettings = 'ReadSettings',
-    UpdateSettings = 'UpdateSettings',
-    DeleteSettings = 'DeleteSettings',
-}
-
 export type Address = Node & {
 export type Address = Node & {
     id: Scalars['ID'];
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     createdAt: Scalars['DateTime'];

+ 66 - 43
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -344,6 +344,72 @@ export enum DeletionResult {
     NOT_DELETED = 'NOT_DELETED',
     NOT_DELETED = 'NOT_DELETED',
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ *
+ * @docsCategory common
+ */
+export enum Permission {
+    /** Authenticated means simply that the user is logged in */
+    Authenticated = 'Authenticated',
+    /** SuperAdmin has unrestricted access to all operations */
+    SuperAdmin = 'SuperAdmin',
+    /** Owner means the user owns this entity, e.g. a Customer's own Order */
+    Owner = 'Owner',
+    /** Public means any unauthenticated user may perform the operation */
+    Public = 'Public',
+    /** Grants permission to Create Catalog */
+    CreateCatalog = 'CreateCatalog',
+    /** Grants permission to Read Catalog */
+    ReadCatalog = 'ReadCatalog',
+    /** Grants permission to Update Catalog */
+    UpdateCatalog = 'UpdateCatalog',
+    /** Grants permission to Delete Catalog */
+    DeleteCatalog = 'DeleteCatalog',
+    /** Grants permission to Create Customer */
+    CreateCustomer = 'CreateCustomer',
+    /** Grants permission to Read Customer */
+    ReadCustomer = 'ReadCustomer',
+    /** Grants permission to Update Customer */
+    UpdateCustomer = 'UpdateCustomer',
+    /** Grants permission to Delete Customer */
+    DeleteCustomer = 'DeleteCustomer',
+    /** Grants permission to Create Administrator */
+    CreateAdministrator = 'CreateAdministrator',
+    /** Grants permission to Read Administrator */
+    ReadAdministrator = 'ReadAdministrator',
+    /** Grants permission to Update Administrator */
+    UpdateAdministrator = 'UpdateAdministrator',
+    /** Grants permission to Delete Administrator */
+    DeleteAdministrator = 'DeleteAdministrator',
+    /** Grants permission to Create Order */
+    CreateOrder = 'CreateOrder',
+    /** Grants permission to Read Order */
+    ReadOrder = 'ReadOrder',
+    /** Grants permission to Update Order */
+    UpdateOrder = 'UpdateOrder',
+    /** Grants permission to Delete Order */
+    DeleteOrder = 'DeleteOrder',
+    /** Grants permission to Create Promotion */
+    CreatePromotion = 'CreatePromotion',
+    /** Grants permission to Read Promotion */
+    ReadPromotion = 'ReadPromotion',
+    /** Grants permission to Update Promotion */
+    UpdatePromotion = 'UpdatePromotion',
+    /** Grants permission to Delete Promotion */
+    DeletePromotion = 'DeletePromotion',
+    /** Grants permission to Create Settings */
+    CreateSettings = 'CreateSettings',
+    /** Grants permission to Read Settings */
+    ReadSettings = 'ReadSettings',
+    /** Grants permission to Update Settings */
+    UpdateSettings = 'UpdateSettings',
+    /** Grants permission to Delete Settings */
+    DeleteSettings = 'DeleteSettings',
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
     result: DeletionResult;
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
     message?: Maybe<Scalars['String']>;
@@ -1291,49 +1357,6 @@ export enum LanguageCode {
     zu = 'zu',
     zu = 'zu',
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- *
- * @docsCategory common
- */
-export enum Permission {
-    /**  The Authenticated role means simply that the user is logged in  */
-    Authenticated = 'Authenticated',
-    /**  SuperAdmin can perform the most sensitive tasks */
-    SuperAdmin = 'SuperAdmin',
-    /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-    Owner = 'Owner',
-    /**  Public means any unauthenticated user may perform the operation  */
-    Public = 'Public',
-    CreateCatalog = 'CreateCatalog',
-    ReadCatalog = 'ReadCatalog',
-    UpdateCatalog = 'UpdateCatalog',
-    DeleteCatalog = 'DeleteCatalog',
-    CreateCustomer = 'CreateCustomer',
-    ReadCustomer = 'ReadCustomer',
-    UpdateCustomer = 'UpdateCustomer',
-    DeleteCustomer = 'DeleteCustomer',
-    CreateAdministrator = 'CreateAdministrator',
-    ReadAdministrator = 'ReadAdministrator',
-    UpdateAdministrator = 'UpdateAdministrator',
-    DeleteAdministrator = 'DeleteAdministrator',
-    CreateOrder = 'CreateOrder',
-    ReadOrder = 'ReadOrder',
-    UpdateOrder = 'UpdateOrder',
-    DeleteOrder = 'DeleteOrder',
-    CreatePromotion = 'CreatePromotion',
-    ReadPromotion = 'ReadPromotion',
-    UpdatePromotion = 'UpdatePromotion',
-    DeletePromotion = 'DeletePromotion',
-    CreateSettings = 'CreateSettings',
-    ReadSettings = 'ReadSettings',
-    UpdateSettings = 'UpdateSettings',
-    DeleteSettings = 'DeleteSettings',
-}
-
 export type RegisterCustomerInput = {
 export type RegisterCustomerInput = {
     emailAddress: Scalars['String'];
     emailAddress: Scalars['String'];
     title?: Maybe<Scalars['String']>;
     title?: Maybe<Scalars['String']>;

+ 2 - 0
packages/core/src/api/config/configure-graphql-module.ts

@@ -28,6 +28,7 @@ import { TranslateErrorsPlugin } from '../middleware/translate-errors-plugin';
 import { generateAuthenticationTypes } from './generate-auth-types';
 import { generateAuthenticationTypes } from './generate-auth-types';
 import { generateErrorCodeEnum } from './generate-error-code-enum';
 import { generateErrorCodeEnum } from './generate-error-code-enum';
 import { generateListOptions } from './generate-list-options';
 import { generateListOptions } from './generate-list-options';
+import { generatePermissionEnum } from './generate-permissions';
 import {
 import {
     addGraphQLCustomFields,
     addGraphQLCustomFields,
     addOrderLineCustomFieldsInput,
     addOrderLineCustomFieldsInput,
@@ -190,6 +191,7 @@ async function createGraphQLOptions(
             .map(e => (typeof e.schema === 'function' ? e.schema() : e.schema))
             .map(e => (typeof e.schema === 'function' ? e.schema() : e.schema))
             .filter(notNullOrUndefined)
             .filter(notNullOrUndefined)
             .forEach(documentNode => (schema = extendSchema(schema, documentNode)));
             .forEach(documentNode => (schema = extendSchema(schema, documentNode)));
+        schema = generatePermissionEnum(schema, configService.authOptions.customPermissions);
         schema = generateListOptions(schema);
         schema = generateListOptions(schema);
         schema = addGraphQLCustomFields(schema, customFields, apiType === 'shop');
         schema = addGraphQLCustomFields(schema, customFields, apiType === 'shop');
         schema = addServerConfigCustomFields(schema, customFields);
         schema = addServerConfigCustomFields(schema, customFields);

+ 39 - 0
packages/core/src/api/config/generate-permissions.ts

@@ -0,0 +1,39 @@
+import { stitchSchemas } from '@graphql-tools/stitch';
+import { GraphQLEnumType, GraphQLInputObjectType, GraphQLSchema } from 'graphql';
+import { GraphQLEnumValueConfigMap } from 'graphql/type/definition';
+
+import { DEFAULT_PERMISSIONS } from '../../common/constants';
+import { getAllPermissionsMetadata, PermissionDefinition } from '../../common/permission-definition';
+
+const PERMISSION_DESCRIPTION = `@description
+Permissions for administrators and customers. Used to control access to
+GraphQL resolvers via the {@link Allow} decorator.
+
+@docsCategory common`;
+
+/**
+ * Generates the `Permission` GraphQL enum based on the default & custom permission definitions.
+ */
+export function generatePermissionEnum(
+    schema: GraphQLSchema,
+    customPermissions: PermissionDefinition[],
+): GraphQLSchema {
+    const allPermissionsMetadata = getAllPermissionsMetadata(customPermissions);
+    const values: GraphQLEnumValueConfigMap = {};
+    let i = 0;
+    for (const entry of allPermissionsMetadata) {
+        values[entry.name] = {
+            value: i,
+            description: entry.description,
+        };
+        i++;
+    }
+
+    const permissionsEnum = new GraphQLEnumType({
+        name: 'Permission',
+        description: PERMISSION_DESCRIPTION,
+        values,
+    });
+
+    return stitchSchemas({ schemas: [schema, [permissionsEnum]] });
+}

+ 5 - 0
packages/core/src/api/schema/common/common-types.graphql

@@ -58,6 +58,11 @@ enum DeletionResult {
     NOT_DELETED
     NOT_DELETED
 }
 }
 
 
+# Populated at run-time
+enum Permission {
+    Placeholder
+}
+
 type DeletionResponse {
 type DeletionResponse {
     result: DeletionResult!
     result: DeletionResult!
     message: String
     message: String

+ 0 - 47
packages/core/src/api/schema/common/permission.graphql

@@ -1,47 +0,0 @@
-""""
-@description
-Permissions for administrators and customers. Used to control access to
-GraphQL resolvers via the {@link Allow} decorator.
-
-@docsCategory common
-"""
-enum Permission {
-    " The Authenticated role means simply that the user is logged in "
-    Authenticated
-    " SuperAdmin can perform the most sensitive tasks"
-    SuperAdmin
-    " Owner means the user owns this entity, e.g. a Customer's own Order"
-    Owner
-    " Public means any unauthenticated user may perform the operation "
-    Public
-
-    CreateCatalog
-    ReadCatalog
-    UpdateCatalog
-    DeleteCatalog
-
-    CreateCustomer
-    ReadCustomer
-    UpdateCustomer
-    DeleteCustomer
-
-    CreateAdministrator
-    ReadAdministrator
-    UpdateAdministrator
-    DeleteAdministrator
-
-    CreateOrder
-    ReadOrder
-    UpdateOrder
-    DeleteOrder
-
-    CreatePromotion
-    ReadPromotion
-    UpdatePromotion
-    DeletePromotion
-
-    CreateSettings
-    ReadSettings
-    UpdateSettings
-    DeleteSettings
-}

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

@@ -1,5 +1,7 @@
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 
 
+import { CrudPermissionDefinition, PermissionDefinition } from './permission-definition';
+
 /**
 /**
  * This value should be rarely used - only in those contexts where we have no access to the
  * This value should be rarely used - only in those contexts where we have no access to the
  * VendureConfig to ensure at least a valid LanguageCode is available.
  * VendureConfig to ensure at least a valid LanguageCode is available.
@@ -7,3 +9,28 @@ import { LanguageCode } from '@vendure/common/lib/generated-types';
 export const DEFAULT_LANGUAGE_CODE = LanguageCode.en;
 export const DEFAULT_LANGUAGE_CODE = LanguageCode.en;
 export const TRANSACTION_MANAGER_KEY = Symbol('TRANSACTION_MANAGER');
 export const TRANSACTION_MANAGER_KEY = Symbol('TRANSACTION_MANAGER');
 export const REQUEST_CONTEXT_KEY = 'vendureRequestContext';
 export const REQUEST_CONTEXT_KEY = 'vendureRequestContext';
+export const DEFAULT_PERMISSIONS: PermissionDefinition[] = [
+    new PermissionDefinition({
+        name: 'Authenticated',
+        description: 'Authenticated means simply that the user is logged in',
+    }),
+    new PermissionDefinition({
+        name: 'SuperAdmin',
+        description: 'SuperAdmin has unrestricted access to all operations',
+    }),
+    new PermissionDefinition({
+        name: 'Owner',
+        description: `Owner means the user owns this entity, e.g. a Customer's own Order`,
+        assignable: false,
+    }),
+    new PermissionDefinition({
+        name: 'Public',
+        description: `Public means any unauthenticated user may perform the operation`,
+    }),
+    new CrudPermissionDefinition('Catalog'),
+    new CrudPermissionDefinition('Customer'),
+    new CrudPermissionDefinition('Administrator'),
+    new CrudPermissionDefinition('Order'),
+    new CrudPermissionDefinition('Promotion'),
+    new CrudPermissionDefinition('Settings'),
+];

+ 1 - 0
packages/core/src/common/index.ts

@@ -5,6 +5,7 @@ export * from './error/errors';
 export * from './error/error-result';
 export * from './error/error-result';
 export * from './error/generated-graphql-admin-errors';
 export * from './error/generated-graphql-admin-errors';
 export * from './injector';
 export * from './injector';
+export * from './permission-definition';
 export * from './ttl-cache';
 export * from './ttl-cache';
 export * from './types/common-types';
 export * from './types/common-types';
 export * from './types/injectable-strategy';
 export * from './types/injectable-strategy';

+ 193 - 0
packages/core/src/common/permission-definition.ts

@@ -0,0 +1,193 @@
+import { Permission } from '@vendure/common/lib/generated-types';
+
+import { DEFAULT_PERMISSIONS } from './constants';
+
+/**
+ * @description
+ * Configures a {@link PermissionDefinition}
+ *
+ * @docsCategory auth
+ * @docsPage PermissionDefinition
+ */
+export interface PermissionDefinitionConfig {
+    /**
+     * @description
+     * The name of the permission. By convention this should be
+     * UpperCamelCased.
+     */
+    name: string;
+    /**
+     * @description
+     * A description of the permission.
+     */
+    description?: string;
+    /**
+     * @description
+     * Whether this permission can be assigned to a Role. In general this
+     * should be left as the default `true` except in special cases.
+     *
+     * @default true
+     */
+    assignable?: boolean;
+}
+
+/**
+ * @description
+ * Permission metadata used internally in generating the GraphQL `Permissions` enum.
+ *
+ * @internal
+ */
+export type PermissionMetadata = Required<PermissionDefinitionConfig>;
+
+/**
+ * @description
+ * Defines a new Permission with which to control access to GraphQL resolvers & REST controllers.
+ * Used in conjunction with the {@link Allow} decorator (see example below).
+ *
+ * **Note:** To define CRUD permissions, use the {@link CrudPermissionDefinition}.
+ *
+ * @example
+ * ```TypeScript
+ * export const sync = new PermissionDefinition({
+ *   name: 'SyncInventory',
+ *   description: 'Allows syncing stock levels via Admin API'
+ * });
+ * ```
+ *
+ * ```TypeScript
+ * const config: VendureConfig = {
+ *   authOptions: {
+ *     customPermissions: [sync],
+ *   },
+ * }
+ * ```
+ *
+ * ```TypeScript
+ * \@Resolver()
+ * export class ExternalSyncResolver {
+ *
+ *   \@Allow(sync.Permission)
+ *   \@Mutation()
+ *   syncStockLevels() {
+ *     // ...
+ *   }
+ * }
+ * ```
+ * @docsCategory auth
+ * @docsPage PermissionDefinition
+ * @docsWeight 0
+ */
+export class PermissionDefinition {
+    constructor(protected config: PermissionDefinitionConfig) {}
+
+    /** @internal */
+    getMetadata(): PermissionMetadata[] {
+        const { name, description, assignable } = this.config;
+        return [
+            {
+                name,
+                description: description || `Grants permissions on ${name} operations`,
+                assignable: assignable ?? true,
+            },
+        ];
+    }
+
+    /**
+     * @description
+     * Returns the permission defined by this definition, for use in the
+     * {@link Allow} decorator.
+     */
+    get Permission(): Permission {
+        return this.config.name as Permission;
+    }
+}
+
+/**
+ * @description
+ * Defines a set of CRUD Permissions for the given name, i.e. a `name` of 'Wishlist' will create
+ * 4 Permissions: 'CreateWishlist', 'ReadWishlist', 'UpdateWishlist' & 'DeleteWishlist'.
+ *
+ * @example
+ * ```TypeScript
+ * export const wishlist = new CrudPermissionDefinition('Wishlist');
+ * ```
+ *
+ * ```TypeScript
+ * const config: VendureConfig = {
+ *   authOptions: {
+ *     customPermissions: [wishlist],
+ *   },
+ * }
+ * ```
+ *
+ * ```TypeScript
+ * \@Resolver()
+ * export class WishlistResolver {
+ *
+ *   \@Allow(wishlist.Create)
+ *   \@Mutation()
+ *   createWishlist() {
+ *     // ...
+ *   }
+ * }
+ * ```
+ *
+ * @docsCategory auth
+ * @docsPage PermissionDefinition
+ * @docsWeight 1
+ */
+export class CrudPermissionDefinition extends PermissionDefinition {
+    constructor(name: string) {
+        super({ name });
+    }
+
+    /** @internal */
+    getMetadata(): PermissionMetadata[] {
+        return ['Create', 'Read', 'Update', 'Delete'].map(operation => ({
+            name: `${operation}${this.config.name}`,
+            description: `Grants permission to ${operation.toLocaleLowerCase()} ${this.config.name}`,
+            assignable: true,
+        }));
+    }
+
+    /**
+     * @description
+     * Returns the 'Create' CRUD permission defined by this definition, for use in the
+     * {@link Allow} decorator.
+     */
+    get Create(): Permission {
+        return `Create${this.config.name}` as Permission;
+    }
+
+    /**
+     * @description
+     * Returns the 'Read' CRUD permission defined by this definition, for use in the
+     * {@link Allow} decorator.
+     */
+    get Read(): Permission {
+        return `Read${this.config.name}` as Permission;
+    }
+
+    /**
+     * @description
+     * Returns the 'Update' CRUD permission defined by this definition, for use in the
+     * {@link Allow} decorator.
+     */
+    get Update(): Permission {
+        return `Update${this.config.name}` as Permission;
+    }
+
+    /**
+     * @description
+     * Returns the 'Delete' CRUD permission defined by this definition, for use in the
+     * {@link Allow} decorator.
+     */
+    get Delete(): Permission {
+        return `Delete${this.config.name}` as Permission;
+    }
+}
+
+export function getAllPermissionsMetadata(customPermissions: PermissionDefinition[]): PermissionMetadata[] {
+    const allPermissions = [...DEFAULT_PERMISSIONS, ...customPermissions];
+    return allPermissions.reduce((all, def) => [...all, ...def.getMetadata()], [] as PermissionMetadata[]);
+}

+ 1 - 0
packages/core/src/config/default-config.ts

@@ -76,6 +76,7 @@ export const defaultConfig: RuntimeVendureConfig = {
         },
         },
         shopAuthenticationStrategy: [new NativeAuthenticationStrategy()],
         shopAuthenticationStrategy: [new NativeAuthenticationStrategy()],
         adminAuthenticationStrategy: [new NativeAuthenticationStrategy()],
         adminAuthenticationStrategy: [new NativeAuthenticationStrategy()],
+        customPermissions: [],
     },
     },
     catalogOptions: {
     catalogOptions: {
         collectionFilters: defaultCollectionFilters,
         collectionFilters: defaultCollectionFilters,

+ 9 - 0
packages/core/src/config/vendure-config.ts

@@ -9,6 +9,7 @@ import { ConnectionOptions } from 'typeorm';
 
 
 import { RequestContext } from '../api/common/request-context';
 import { RequestContext } from '../api/common/request-context';
 import { Transitions } from '../common/finite-state-machine/types';
 import { Transitions } from '../common/finite-state-machine/types';
+import { PermissionDefinition } from '../common/permission-definition';
 import { Order } from '../entity/order/order.entity';
 import { Order } from '../entity/order/order.entity';
 import { OrderState } from '../service/helpers/order-state-machine/order-state';
 import { OrderState } from '../service/helpers/order-state-machine/order-state';
 
 
@@ -352,6 +353,14 @@ export interface AuthOptions {
      * @default NativeAuthenticationStrategy
      * @default NativeAuthenticationStrategy
      */
      */
     adminAuthenticationStrategy?: AuthenticationStrategy[];
     adminAuthenticationStrategy?: AuthenticationStrategy[];
+    /**
+     * @description
+     * Allows custom Permissions to be defined, which can be used to restrict access to custom
+     * GraphQL resolvers defined in plugins.
+     *
+     * @default []
+     */
+    customPermissions?: PermissionDefinition[];
 }
 }
 
 
 /**
 /**

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

@@ -22,8 +22,10 @@ import {
     InternalServerError,
     InternalServerError,
     UserInputError,
     UserInputError,
 } from '../../common/error/errors';
 } from '../../common/error/errors';
+import { getAllPermissionsMetadata } from '../../common/permission-definition';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { assertFound, idsAreEqual } from '../../common/utils';
+import { ConfigService } from '../../config/config.service';
 import { Channel } from '../../entity/channel/channel.entity';
 import { Channel } from '../../entity/channel/channel.entity';
 import { Role } from '../../entity/role/role.entity';
 import { Role } from '../../entity/role/role.entity';
 import { User } from '../../entity/user/user.entity';
 import { User } from '../../entity/user/user.entity';
@@ -40,6 +42,7 @@ export class RoleService {
         private connection: TransactionalConnection,
         private connection: TransactionalConnection,
         private channelService: ChannelService,
         private channelService: ChannelService,
         private listQueryBuilder: ListQueryBuilder,
         private listQueryBuilder: ListQueryBuilder,
+        private configService: ConfigService,
     ) {}
     ) {}
 
 
     async initRoles() {
     async initRoles() {
@@ -191,11 +194,12 @@ export class RoleService {
         return permittedChannels;
         return permittedChannels;
     }
     }
 
 
-    private checkPermissionsAreValid(permissions?: string[] | null) {
+    private checkPermissionsAreValid(permissions?: Permission[] | null) {
         if (!permissions) {
         if (!permissions) {
             return;
             return;
         }
         }
-        const allPermissions = this.getAllPermissions();
+        const { customPermissions } = this.configService.authOptions;
+        const allPermissions = getAllPermissionsMetadata(customPermissions).map(p => p.name as Permission);
         for (const permission of permissions) {
         for (const permission of permissions) {
             if (!allPermissions.includes(permission)) {
             if (!allPermissions.includes(permission)) {
                 throw new UserInputError('error.permission-invalid', { permission });
                 throw new UserInputError('error.permission-invalid', { permission });
@@ -213,14 +217,17 @@ export class RoleService {
      * Ensure that the SuperAdmin role exists and that it has all possible Permissions.
      * Ensure that the SuperAdmin role exists and that it has all possible Permissions.
      */
      */
     private async ensureSuperAdminRoleExists() {
     private async ensureSuperAdminRoleExists() {
-        const allPermissions = Object.values(Permission).filter(p => p !== Permission.Owner);
+        const { customPermissions } = this.configService.authOptions;
+        const assignablePermissions = getAllPermissionsMetadata(customPermissions)
+            .filter(p => p.assignable)
+            .map(p => p.name as Permission);
         try {
         try {
             const superAdminRole = await this.getSuperAdminRole();
             const superAdminRole = await this.getSuperAdminRole();
-            const hasAllPermissions = allPermissions.every(permission =>
+            const hasAllPermissions = assignablePermissions.every(permission =>
                 superAdminRole.permissions.includes(permission),
                 superAdminRole.permissions.includes(permission),
             );
             );
             if (!hasAllPermissions) {
             if (!hasAllPermissions) {
-                superAdminRole.permissions = allPermissions;
+                superAdminRole.permissions = assignablePermissions;
                 await this.connection.getRepository(Role).save(superAdminRole, { reload: false });
                 await this.connection.getRepository(Role).save(superAdminRole, { reload: false });
             }
             }
         } catch (err) {
         } catch (err) {
@@ -229,7 +236,7 @@ export class RoleService {
                 {
                 {
                     code: SUPER_ADMIN_ROLE_CODE,
                     code: SUPER_ADMIN_ROLE_CODE,
                     description: SUPER_ADMIN_ROLE_DESCRIPTION,
                     description: SUPER_ADMIN_ROLE_DESCRIPTION,
-                    permissions: allPermissions,
+                    permissions: assignablePermissions,
                 },
                 },
                 [this.channelService.getDefaultChannel()],
                 [this.channelService.getDefaultChannel()],
             );
             );

+ 66 - 43
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -1795,6 +1795,72 @@ export enum DeletionResult {
     NOT_DELETED = 'NOT_DELETED',
     NOT_DELETED = 'NOT_DELETED',
 }
 }
 
 
+/**
+ * @description
+ * Permissions for administrators and customers. Used to control access to
+ * GraphQL resolvers via the {@link Allow} decorator.
+ *
+ * @docsCategory common
+ */
+export enum Permission {
+    /** Authenticated means simply that the user is logged in */
+    Authenticated = 'Authenticated',
+    /** SuperAdmin has unrestricted access to all operations */
+    SuperAdmin = 'SuperAdmin',
+    /** Owner means the user owns this entity, e.g. a Customer's own Order */
+    Owner = 'Owner',
+    /** Public means any unauthenticated user may perform the operation */
+    Public = 'Public',
+    /** Grants permission to Create Catalog */
+    CreateCatalog = 'CreateCatalog',
+    /** Grants permission to Read Catalog */
+    ReadCatalog = 'ReadCatalog',
+    /** Grants permission to Update Catalog */
+    UpdateCatalog = 'UpdateCatalog',
+    /** Grants permission to Delete Catalog */
+    DeleteCatalog = 'DeleteCatalog',
+    /** Grants permission to Create Customer */
+    CreateCustomer = 'CreateCustomer',
+    /** Grants permission to Read Customer */
+    ReadCustomer = 'ReadCustomer',
+    /** Grants permission to Update Customer */
+    UpdateCustomer = 'UpdateCustomer',
+    /** Grants permission to Delete Customer */
+    DeleteCustomer = 'DeleteCustomer',
+    /** Grants permission to Create Administrator */
+    CreateAdministrator = 'CreateAdministrator',
+    /** Grants permission to Read Administrator */
+    ReadAdministrator = 'ReadAdministrator',
+    /** Grants permission to Update Administrator */
+    UpdateAdministrator = 'UpdateAdministrator',
+    /** Grants permission to Delete Administrator */
+    DeleteAdministrator = 'DeleteAdministrator',
+    /** Grants permission to Create Order */
+    CreateOrder = 'CreateOrder',
+    /** Grants permission to Read Order */
+    ReadOrder = 'ReadOrder',
+    /** Grants permission to Update Order */
+    UpdateOrder = 'UpdateOrder',
+    /** Grants permission to Delete Order */
+    DeleteOrder = 'DeleteOrder',
+    /** Grants permission to Create Promotion */
+    CreatePromotion = 'CreatePromotion',
+    /** Grants permission to Read Promotion */
+    ReadPromotion = 'ReadPromotion',
+    /** Grants permission to Update Promotion */
+    UpdatePromotion = 'UpdatePromotion',
+    /** Grants permission to Delete Promotion */
+    DeletePromotion = 'DeletePromotion',
+    /** Grants permission to Create Settings */
+    CreateSettings = 'CreateSettings',
+    /** Grants permission to Read Settings */
+    ReadSettings = 'ReadSettings',
+    /** Grants permission to Update Settings */
+    UpdateSettings = 'UpdateSettings',
+    /** Grants permission to Delete Settings */
+    DeleteSettings = 'DeleteSettings',
+}
+
 export type DeletionResponse = {
 export type DeletionResponse = {
     result: DeletionResult;
     result: DeletionResult;
     message?: Maybe<Scalars['String']>;
     message?: Maybe<Scalars['String']>;
@@ -2741,49 +2807,6 @@ export enum LanguageCode {
     zu = 'zu',
     zu = 'zu',
 }
 }
 
 
-/**
- * "
- * @description
- * Permissions for administrators and customers. Used to control access to
- * GraphQL resolvers via the {@link Allow} decorator.
- *
- * @docsCategory common
- */
-export enum Permission {
-    /**  The Authenticated role means simply that the user is logged in  */
-    Authenticated = 'Authenticated',
-    /**  SuperAdmin can perform the most sensitive tasks */
-    SuperAdmin = 'SuperAdmin',
-    /**  Owner means the user owns this entity, e.g. a Customer's own Order */
-    Owner = 'Owner',
-    /**  Public means any unauthenticated user may perform the operation  */
-    Public = 'Public',
-    CreateCatalog = 'CreateCatalog',
-    ReadCatalog = 'ReadCatalog',
-    UpdateCatalog = 'UpdateCatalog',
-    DeleteCatalog = 'DeleteCatalog',
-    CreateCustomer = 'CreateCustomer',
-    ReadCustomer = 'ReadCustomer',
-    UpdateCustomer = 'UpdateCustomer',
-    DeleteCustomer = 'DeleteCustomer',
-    CreateAdministrator = 'CreateAdministrator',
-    ReadAdministrator = 'ReadAdministrator',
-    UpdateAdministrator = 'UpdateAdministrator',
-    DeleteAdministrator = 'DeleteAdministrator',
-    CreateOrder = 'CreateOrder',
-    ReadOrder = 'ReadOrder',
-    UpdateOrder = 'UpdateOrder',
-    DeleteOrder = 'DeleteOrder',
-    CreatePromotion = 'CreatePromotion',
-    ReadPromotion = 'ReadPromotion',
-    UpdatePromotion = 'UpdatePromotion',
-    DeletePromotion = 'DeletePromotion',
-    CreateSettings = 'CreateSettings',
-    ReadSettings = 'ReadSettings',
-    UpdateSettings = 'UpdateSettings',
-    DeleteSettings = 'DeleteSettings',
-}
-
 export type Address = Node & {
 export type Address = Node & {
     id: Scalars['ID'];
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     createdAt: Scalars['DateTime'];

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
schema-admin.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
schema-shop.json


+ 1 - 2
scripts/codegen/client-schema.ts

@@ -5,7 +5,6 @@ import path from 'path';
 const CLIENT_SCHEMA_FILE = '../../packages/admin-ui/src/lib/core/src/data/client-state/client-types.graphql';
 const CLIENT_SCHEMA_FILE = '../../packages/admin-ui/src/lib/core/src/data/client-state/client-types.graphql';
 const LANGUAGE_CODE_FILE = '../../packages/core/src/api/schema/common/language-code.graphql';
 const LANGUAGE_CODE_FILE = '../../packages/core/src/api/schema/common/language-code.graphql';
 const AUTH_TYPE_FILE = '../../packages/core/src/api/schema/type/auth.type.graphql';
 const AUTH_TYPE_FILE = '../../packages/core/src/api/schema/type/auth.type.graphql';
-const PERMISSION_TYPE_FILE = '../../packages/core/src/api/schema/common/permission.graphql';
 
 
 function loadGraphQL(file: string): string {
 function loadGraphQL(file: string): string {
     const filePath = path.join(__dirname, file);
     const filePath = path.join(__dirname, file);
@@ -24,7 +23,7 @@ function getClientSchema() {
     const clientSchemaString = loadGraphQL(CLIENT_SCHEMA_FILE);
     const clientSchemaString = loadGraphQL(CLIENT_SCHEMA_FILE);
     const languageCodeString = loadGraphQL(LANGUAGE_CODE_FILE);
     const languageCodeString = loadGraphQL(LANGUAGE_CODE_FILE);
     const authTypeString = loadGraphQL(AUTH_TYPE_FILE);
     const authTypeString = loadGraphQL(AUTH_TYPE_FILE);
-    const permissionTypeString = loadGraphQL(PERMISSION_TYPE_FILE);
+    const permissionTypeString = `enum Permission { Placeholder }`;
     const schema = makeExecutableSchema({
     const schema = makeExecutableSchema({
         typeDefs: [
         typeDefs: [
             clientSchemaString,
             clientSchemaString,

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff