Browse Source

feat(admin-ui): Add permissions checks to Promotions & Settings views

Relates to #94
Michael Bromley 6 years ago
parent
commit
2552191c7a
20 changed files with 205 additions and 47 deletions
  1. 2 2
      packages/admin-ui/src/app/core/components/main-nav/main-nav.component.html
  2. 16 4
      packages/admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.html
  3. 3 1
      packages/admin-ui/src/app/marketing/components/promotion-list/promotion-list.component.html
  4. 7 6
      packages/admin-ui/src/app/settings/components/admin-detail/admin-detail.component.html
  5. 8 0
      packages/admin-ui/src/app/settings/components/admin-detail/admin-detail.component.ts
  6. 1 1
      packages/admin-ui/src/app/settings/components/administrator-list/administrator-list.component.html
  7. 33 7
      packages/admin-ui/src/app/settings/components/channel-detail/channel-detail.component.html
  8. 1 1
      packages/admin-ui/src/app/settings/components/channel-list/channel-list.component.html
  9. 20 3
      packages/admin-ui/src/app/settings/components/country-detail/country-detail.component.html
  10. 3 2
      packages/admin-ui/src/app/settings/components/country-list/country-list.component.html
  11. 8 1
      packages/admin-ui/src/app/settings/components/global-settings/global-settings.component.html
  12. 8 0
      packages/admin-ui/src/app/settings/components/global-settings/global-settings.component.ts
  13. 33 5
      packages/admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.html
  14. 6 2
      packages/admin-ui/src/app/settings/components/shipping-method-detail/shipping-method-detail.component.html
  15. 2 1
      packages/admin-ui/src/app/settings/components/shipping-method-list/shipping-method-list.component.html
  16. 13 3
      packages/admin-ui/src/app/settings/components/tax-category-detail/tax-category-detail.component.html
  17. 1 1
      packages/admin-ui/src/app/settings/components/tax-category-list/tax-category-list.component.html
  18. 38 6
      packages/admin-ui/src/app/settings/components/tax-rate-detail/tax-rate-detail.component.html
  19. 1 1
      packages/admin-ui/src/app/settings/components/tax-rate-list/tax-rate-list.component.html
  20. 1 0
      packages/admin-ui/src/i18n-messages/en.json

+ 2 - 2
packages/admin-ui/src/app/core/components/main-nav/main-nav.component.html

@@ -86,7 +86,7 @@
                         {{ 'nav.channels' | translate }}
                     </a>
                 </li>
-                <li>
+                <li *vdrIfPermissions="'ReadAdministrator'">
                     <a
                         class="nav-link"
                         [routerLink]="['/settings', 'administrators']"
@@ -96,7 +96,7 @@
                         {{ 'nav.administrators' | translate }}
                     </a>
                 </li>
-                <li>
+                <li *vdrIfPermissions="'ReadAdministrator'">
                     <a class="nav-link" [routerLink]="['/settings', 'roles']" routerLinkActive="active">
                         <clr-icon shape="users" size="20"></clr-icon>
                         {{ 'nav.roles' | translate }}

+ 16 - 4
packages/admin-ui/src/app/marketing/components/promotion-detail/promotion-detail.component.html

@@ -11,7 +11,12 @@
             {{ 'common.create' | translate }}
         </button>
         <ng-template #updateButton>
-            <button class="btn btn-primary" (click)="save()" [disabled]="!saveButtonEnabled()">
+            <button
+                class="btn btn-primary"
+                (click)="save()"
+                *vdrIfPermissions="'UpdatePromotion'"
+                [disabled]="!saveButtonEnabled()"
+            >
                 {{ 'common.update' | translate }}
             </button>
         </ng-template>
@@ -20,7 +25,12 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.name' | translate" for="name">
-        <input id="name" type="text" formControlName="name" />
+        <input
+            id="name"
+            [readonly]="!('UpdatePromotion' | hasPermission)"
+            type="text"
+            formControlName="name"
+        />
     </vdr-form-field>
 
     <div class="clr-row">
@@ -30,6 +40,7 @@
                 <vdr-configurable-input
                     (remove)="removeCondition($event)"
                     [facets]="facets$ | async"
+                    [readonly]="!('UpdatePromotion' | hasPermission)"
                     [operation]="condition"
                     [operationDefinition]="getConditionDefinition(condition)"
                     [formControlName]="i"
@@ -38,7 +49,7 @@
             </ng-container>
 
             <div>
-                <vdr-dropdown>
+                <vdr-dropdown *vdrIfPermissions="'UpdatePromotion'">
                     <button class="btn btn-outline" vdrDropdownTrigger>
                         <clr-icon shape="plus"></clr-icon>
                         {{ 'marketing.add-condition' | translate }}
@@ -63,12 +74,13 @@
                 (remove)="removeAction($event)"
                 [facets]="facets$ | async"
                 [operation]="action"
+                [readonly]="!('UpdatePromotion' | hasPermission)"
                 [operationDefinition]="getActionDefinition(action)"
                 [formControlName]="i"
                 [activeChannel]="activeChannel$ | async"
             ></vdr-configurable-input>
             <div>
-                <vdr-dropdown>
+                <vdr-dropdown *vdrIfPermissions="'UpdatePromotion'">
                     <button class="btn btn-outline" vdrDropdownTrigger>
                         <clr-icon shape="plus"></clr-icon>
                         {{ 'marketing.add-action' | translate }}

+ 3 - 1
packages/admin-ui/src/app/marketing/components/promotion-list/promotion-list.component.html

@@ -1,6 +1,8 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary"
+           *vdrIfPermissions="'CreatePromotion'"
+           [routerLink]="['./create']">
             <clr-icon shape="plus"></clr-icon>
             {{ 'marketing.create-new-promotion' | translate }}
         </a>

+ 7 - 6
packages/admin-ui/src/app/settings/components/admin-detail/admin-detail.component.html

@@ -13,6 +13,7 @@
             <button
                 class="btn btn-primary"
                 (click)="save()"
+                *vdrIfPermissions="'UpdateAdministrator'"
                 [disabled]="(detailForm.invalid || detailForm.pristine) && !permissionsChanged"
             >
                 {{ 'common.update' | translate }}
@@ -23,24 +24,24 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'settings.email-address' | translate" for="emailAddress">
-        <input id="emailAddress" type="text" formControlName="emailAddress" />
+        <input id="emailAddress" type="text" formControlName="emailAddress" [readonly]="!('UpdateAdministrator' | hasPermission)"/>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.first-name' | translate" for="firstName">
-        <input id="firstName" type="text" formControlName="firstName" />
+        <input id="firstName" type="text" formControlName="firstName" [readonly]="!('UpdateAdministrator' | hasPermission)"/>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.last-name' | translate" for="lastName">
-        <input id="lastName" type="text" formControlName="lastName" />
+        <input id="lastName" type="text" formControlName="lastName" [readonly]="!('UpdateAdministrator' | hasPermission)"/>
     </vdr-form-field>
     <vdr-form-field *ngIf="(isNew$ | async)" [label]="'settings.password' | translate" for="password">
-        <input id="password" type="password" formControlName="password" />
+        <input id="password" type="password" formControlName="password"/>
     </vdr-form-field>
     <vdr-form-field
-        *ngIf="!(isNew$ | async)"
+        *ngIf="!(isNew$ | async) && ('UpdateAdministrator' | hasPermission)"
         [label]="'settings.password' | translate"
         for="password"
         [readOnlyToggle]="true"
     >
-        <input id="password" type="password" formControlName="password" />
+        <input id="password" type="password" formControlName="password"/>
     </vdr-form-field>
     <label class="clr-control-label">{{ 'settings.roles' | translate }}</label>
     <ng-select

+ 8 - 0
packages/admin-ui/src/app/settings/components/admin-detail/admin-detail.component.ts

@@ -54,6 +54,14 @@ export class AdminDetailComponent extends BaseDetailComponent<Administrator> imp
         this.init();
         this.administrator$ = this.entity$;
         this.allRoles$ = this.dataService.administrator.getRoles(99999).mapStream(item => item.roles.items);
+        this.dataService.client.userStatus().single$.subscribe(({ userStatus }) => {
+            if (!userStatus.permissions.includes('UpdateAdministrator')) {
+                const rolesSelect = this.detailForm.get('roles');
+                if (rolesSelect) {
+                    rolesSelect.disable();
+                }
+            }
+        });
     }
 
     ngOnDestroy(): void {

+ 1 - 1
packages/admin-ui/src/app/settings/components/administrator-list/administrator-list.component.html

@@ -1,6 +1,6 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'CreateAdministrator'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'admin.create-new-administrator' | translate }}
         </a>

+ 33 - 7
packages/admin-ui/src/app/settings/components/channel-detail/channel-detail.component.html

@@ -11,7 +11,12 @@
             {{ 'common.create' | translate }}
         </button>
         <ng-template #updateButton>
-            <button class="btn btn-primary" (click)="save()" [disabled]="!saveButtonEnabled()">
+            <button
+                class="btn btn-primary"
+                (click)="save()"
+                *vdrIfPermissions="'SuperAdmin'"
+                [disabled]="!saveButtonEnabled()"
+            >
                 {{ 'common.update' | translate }}
             </button>
         </ng-template>
@@ -20,28 +25,49 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.code' | translate" for="code">
-        <input id="code" type="text" formControlName="code" />
+        <input id="code" type="text" [readonly]="!('SuperAdmin' | hasPermission)" formControlName="code" />
     </vdr-form-field>
     <vdr-form-field [label]="'settings.channel-token' | translate" for="token">
-        <input id="token" type="text" formControlName="token" />
+        <input id="token" type="text" [readonly]="!('SuperAdmin' | hasPermission)" formControlName="token" />
     </vdr-form-field>
     <vdr-form-field [label]="'settings.currency' | translate" for="defaultTaxZoneId">
-        <select clrSelect name="currencyCode" formControlName="currencyCode">
+        <select
+            clrSelect
+            name="currencyCode"
+            formControlName="currencyCode"
+            [attr.disabled]="!('SuperAdmin' | hasPermission)"
+        >
             <option *ngFor="let code of currencyCodes" [value]="code">{{ code | currencyName }}</option>
         </select>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.prices-include-tax' | translate" for="pricesIncludeTax">
         <clr-toggle-wrapper>
-            <input type="checkbox" clrToggle id="pricesIncludeTax" formControlName="pricesIncludeTax" />
+            <input
+                type="checkbox"
+                clrToggle
+                id="pricesIncludeTax"
+                formControlName="pricesIncludeTax"
+                [attr.disabled]="!('SuperAdmin' | hasPermission)"
+            />
         </clr-toggle-wrapper>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.default-tax-zone' | translate" for="defaultTaxZoneId">
-        <select clrSelect name="defaultTaxZoneId" formControlName="defaultTaxZoneId">
+        <select
+            clrSelect
+            name="defaultTaxZoneId"
+            formControlName="defaultTaxZoneId"
+            [attr.disabled]="!('SuperAdmin' | hasPermission)"
+        >
             <option *ngFor="let zone of zones$ | async" [value]="zone.id">{{ zone.name }}</option>
         </select>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.default-shipping-zone' | translate" for="defaultShippingZoneId">
-        <select clrSelect name="defaultShippingZoneId" formControlName="defaultShippingZoneId">
+        <select
+            clrSelect
+            name="defaultShippingZoneId"
+            formControlName="defaultShippingZoneId"
+            [attr.disabled]="!('SuperAdmin' | hasPermission)"
+        >
             <option *ngFor="let zone of zones$ | async" [value]="zone.id">{{ zone.name }}</option>
         </select>
     </vdr-form-field>

+ 1 - 1
packages/admin-ui/src/app/settings/components/channel-list/channel-list.component.html

@@ -1,6 +1,6 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'SuperAdmin'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'settings.create-new-channel' | translate }}
         </a>

+ 20 - 3
packages/admin-ui/src/app/settings/components/country-detail/country-detail.component.html

@@ -19,6 +19,7 @@
         <ng-template #updateButton>
             <button
                 class="btn btn-primary"
+                *vdrIfPermissions="'UpdateSettings'"
                 (click)="save()"
                 [disabled]="detailForm.invalid || detailForm.pristine"
             >
@@ -30,14 +31,30 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.code' | translate" for="code">
-        <input id="code" type="text" formControlName="code" />
+        <input
+            id="code"
+            type="text"
+            formControlName="code"
+            [readonly]="!('UpdateSettings' | hasPermission)"
+        />
     </vdr-form-field>
     <vdr-form-field [label]="'common.name' | translate" for="name">
-        <input id="name" type="text" formControlName="name" />
+        <input
+            id="name"
+            type="text"
+            formControlName="name"
+            [readonly]="!('UpdateSettings' | hasPermission)"
+        />
     </vdr-form-field>
     <vdr-form-field [label]="'common.enabled' | translate" for="enabled">
         <clr-toggle-wrapper>
-            <input type="checkbox" clrToggle id="enabled" formControlName="enabled" />
+            <input
+                type="checkbox"
+                clrToggle
+                id="enabled"
+                formControlName="enabled"
+                [attr.disabled]="!('UpdateSettings' | hasPermission)"
+            />
         </clr-toggle-wrapper>
     </vdr-form-field>
 </form>

+ 3 - 2
packages/admin-ui/src/app/settings/components/country-list/country-list.component.html

@@ -18,7 +18,7 @@
     </vdr-ab-left>
 
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'CreateSettings'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'settings.create-new-country' | translate }}
         </a>
@@ -28,7 +28,7 @@
 <vdr-data-table
     [items]="countriesWithZones$ | async"
     [allSelected]="areAllSelected()"
-    [isRowSelectedFn]="isCountrySelected"
+    [isRowSelectedFn]="('UpdateSettings' | hasPermission) && isCountrySelected"
     (rowSelectChange)="toggleSelectCountry($event)"
     (allSelectChange)="toggleSelectAll()"
 >
@@ -69,6 +69,7 @@
                         class="delete-button"
                         (click)="deleteCountry(country.id)"
                         vdrDropdownItem
+                        [disabled]="!('DeleteSettings' | hasPermission)"
                     >
                         <clr-icon shape="trash" class="is-danger"></clr-icon>
                         {{ 'common.delete' | translate }}

+ 8 - 1
packages/admin-ui/src/app/settings/components/global-settings/global-settings.component.html

@@ -3,6 +3,7 @@
         <button
             class="btn btn-primary"
             (click)="save()"
+            *vdrIfPermissions="'UpdateSettings'"
             [disabled]="detailForm.invalid || detailForm.pristine"
         >
             {{ 'common.update' | translate }}
@@ -32,7 +33,13 @@
         </ng-select>
     </vdr-form-field>
     <clr-toggle-wrapper>
-        <input type="checkbox" clrToggle name="enabled" formControlName="trackInventory" />
+        <input
+            type="checkbox"
+            clrToggle
+            name="enabled"
+            formControlName="trackInventory"
+            [attr.disabled]="!('UpdateSettings' | hasPermission)"
+        />
         <label>{{ 'settings.track-inventory-default' | translate }}</label>
     </clr-toggle-wrapper>
     <section formGroupName="customFields" *ngIf="customFields.length">

+ 8 - 0
packages/admin-ui/src/app/settings/components/global-settings/global-settings.component.ts

@@ -43,6 +43,14 @@ export class GlobalSettingsComponent extends BaseDetailComponent<GlobalSettings>
 
     ngOnInit(): void {
         this.init();
+        this.dataService.client.userStatus().single$.subscribe(({ userStatus }) => {
+            if (!userStatus.permissions.includes('UpdateSettings')) {
+                const languagesSelect = this.detailForm.get('availableLanguages');
+                if (languagesSelect) {
+                    languagesSelect.disable();
+                }
+            }
+        });
     }
 
     customFieldIsSet(name: string): boolean {

+ 33 - 5
packages/admin-ui/src/app/settings/components/payment-method-detail/payment-method-detail.component.html

@@ -11,6 +11,7 @@
         </button>
         <ng-template #updateButton>
             <button
+                *vdrIfPermissions="'UpdateSettings' | hasPermission"
                 class="btn btn-primary"
                 (click)="save()"
                 [disabled]="detailForm.pristine || detailForm.invalid"
@@ -23,11 +24,22 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.code' | translate" for="code">
-        <input id="code" type="text" formControlName="code" />
+        <input
+            id="code"
+            type="text"
+            formControlName="code"
+            [readonly]="!('UpdateSettings' | hasPermission)"
+        />
     </vdr-form-field>
     <vdr-form-field [label]="'common.enabled' | translate" for="description">
         <clr-toggle-wrapper>
-            <input type="checkbox" clrToggle id="enabled" formControlName="enabled" />
+            <input
+                type="checkbox"
+                clrToggle
+                id="enabled"
+                [attr.disabled]="!('UpdateSettings' | hasPermission)"
+                formControlName="enabled"
+            />
         </clr-toggle-wrapper>
     </vdr-form-field>
 
@@ -36,13 +48,29 @@
             <label>{{ 'settings.payment-method-config-options' | translate }}</label>
             <section class="form-block" *ngFor="let arg of (entity$ | async).configArgs">
                 <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="getType(arg) === 'string'">
-                    <input [id]="arg.name" type="text" [formControlName]="arg.name" />
+                    <input
+                        [id]="arg.name"
+                        type="text"
+                        [readonly]="!('UpdateSettings' | hasPermission)"
+                        [formControlName]="arg.name"
+                    />
                 </vdr-form-field>
                 <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="getType(arg) === 'int'">
-                    <input [id]="arg.name" type="number" [formControlName]="arg.name" />
+                    <input
+                        [id]="arg.name"
+                        type="number"
+                        [readonly]="!('UpdateSettings' | hasPermission)"
+                        [formControlName]="arg.name"
+                    />
                 </vdr-form-field>
                 <vdr-form-field [label]="arg.name" [for]="arg.name" *ngIf="getType(arg) === 'boolean'">
-                    <input type="checkbox" [id]="arg.name" [formControlName]="arg.name" clrCheckbox />
+                    <input
+                        type="checkbox"
+                        [id]="arg.name"
+                        [attr.disabled]="!('UpdateSettings' | hasPermission)"
+                        [formControlName]="arg.name"
+                        clrCheckbox
+                    />
                 </vdr-form-field>
             </section>
         </div>

+ 6 - 2
packages/admin-ui/src/app/settings/components/shipping-method-detail/shipping-method-detail.component.html

@@ -14,6 +14,7 @@
             <button
                 class="btn btn-primary"
                 (click)="save()"
+                *vdrIfPermissions="'UpdateSettings'"
                 [disabled]="detailForm.pristine || detailForm.invalid"
             >
                 {{ 'common.update' | translate }}
@@ -28,11 +29,12 @@
             id="description"
             type="text"
             formControlName="description"
+            [readonly]="!('UpdateSettings' | hasPermission)"
             (input)="updateCode(shippingMethod.code, $event.target.value)"
         />
     </vdr-form-field>
-    <vdr-form-field [label]="'common.code' | translate" for="code" [readOnlyToggle]="true">
-        <input id="code" type="text" formControlName="code" />
+    <vdr-form-field [label]="'common.code' | translate" for="code" [readOnlyToggle]="'UpdateSettings' | hasPermission">
+        <input id="code" type="text" formControlName="code" [readonly]="!('UpdateSettings' | hasPermission)" />
     </vdr-form-field>
 
     <div class="clr-row">
@@ -42,6 +44,7 @@
                 *ngIf="selectedChecker"
                 [operation]="selectedChecker"
                 [operationDefinition]="selectedCheckerDefinition"
+                [readonly]="!('UpdateSettings' | hasPermission)"
                 [activeChannel]="activeChannel$ | async"
                 (remove)="selectedChecker = null"
                 formControlName="checker"
@@ -71,6 +74,7 @@
                 *ngIf="selectedCalculator"
                 [operation]="selectedCalculator"
                 [operationDefinition]="selectedCalculatorDefinition"
+                [readonly]="!('UpdateSettings' | hasPermission)"
                 [activeChannel]="activeChannel$ | async"
                 (remove)="selectedCalculator = null"
                 formControlName="calculator"

+ 2 - 1
packages/admin-ui/src/app/settings/components/shipping-method-list/shipping-method-list.component.html

@@ -1,6 +1,6 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'CreateSettings'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'settings.create-new-shipping-method' | translate }}
         </a>
@@ -40,6 +40,7 @@
                         type="button"
                         class="delete-button"
                         (click)="deleteShippingMethod(shippingMethod.id)"
+                        [disabled]="!('DeleteSettings' | hasPermission)"
                         vdrDropdownItem
                     >
                         <clr-icon shape="trash" class="is-danger"></clr-icon>

+ 13 - 3
packages/admin-ui/src/app/settings/components/tax-category-detail/tax-category-detail.component.html

@@ -4,14 +4,19 @@
     <vdr-ab-right>
         <button
             class="btn btn-primary"
-            *ngIf="(isNew$ | async); else updateButton"
+            *ngIf="isNew$ | async; else updateButton"
             (click)="create()"
             [disabled]="!saveButtonEnabled()"
         >
             {{ 'common.create' | translate }}
         </button>
         <ng-template #updateButton>
-            <button class="btn btn-primary" (click)="save()" [disabled]="!saveButtonEnabled()">
+            <button
+                class="btn btn-primary"
+                (click)="save()"
+                [disabled]="!saveButtonEnabled()"
+                *vdrIfPermissions="'UpdateSettings'"
+            >
                 {{ 'common.update' | translate }}
             </button>
         </ng-template>
@@ -20,6 +25,11 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.name' | translate" for="name">
-        <input id="name" type="text" formControlName="name" />
+        <input
+            id="name"
+            type="text"
+            formControlName="name"
+            [readonly]="!('UpdateSettings' | hasPermission)"
+        />
     </vdr-form-field>
 </form>

+ 1 - 1
packages/admin-ui/src/app/settings/components/tax-category-list/tax-category-list.component.html

@@ -1,6 +1,6 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'CreateSettings'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'settings.create-new-tax-category' | translate }}
         </a>

+ 38 - 6
packages/admin-ui/src/app/settings/components/tax-rate-detail/tax-rate-detail.component.html

@@ -11,7 +11,12 @@
             {{ 'common.create' | translate }}
         </button>
         <ng-template #updateButton>
-            <button class="btn btn-primary" (click)="save()" [disabled]="!saveButtonEnabled()">
+            <button
+                class="btn btn-primary"
+                (click)="save()"
+                [disabled]="!saveButtonEnabled()"
+                *vdrIfPermissions="'UpdateSettings'"
+            >
                 {{ 'common.update' | translate }}
             </button>
         </ng-template>
@@ -20,27 +25,54 @@
 
 <form class="form" [formGroup]="detailForm">
     <vdr-form-field [label]="'common.name' | translate" for="name">
-        <input id="name" type="text" formControlName="name" />
+        <input
+            id="name"
+            type="text"
+            formControlName="name"
+            [readonly]="!('UpdateSettings' | hasPermission)"
+        />
     </vdr-form-field>
     <vdr-form-field [label]="'common.enabled' | translate" for="enabled">
         <clr-toggle-wrapper>
-            <input type="checkbox" clrToggle id="enabled" formControlName="enabled" />
+            <input
+                type="checkbox"
+                clrToggle
+                id="enabled"
+                formControlName="enabled"
+                [attr.disabled]="!('UpdateSettings' | hasPermission)"
+            />
         </clr-toggle-wrapper>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.rate' | translate" for="value">
         <vdr-affixed-input suffix="%">
-            <input id="value" type="number" step="0.1" formControlName="value" />
+            <input
+                id="value"
+                type="number"
+                step="0.1"
+                formControlName="value"
+                [readonly]="!('UpdateSettings' | hasPermission)"
+            />
         </vdr-affixed-input>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.tax-category' | translate" for="taxCategoryId">
-        <select clrSelect name="taxCategoryId" formControlName="taxCategoryId">
+        <select
+            clrSelect
+            name="taxCategoryId"
+            formControlName="taxCategoryId"
+            [attr.disabled]="!('UpdateSettings' | hasPermission)"
+        >
             <option *ngFor="let taxCategory of taxCategories$ | async" [value]="taxCategory.id">
                 {{ taxCategory.name }}
             </option>
         </select>
     </vdr-form-field>
     <vdr-form-field [label]="'settings.zone' | translate" for="zoneId">
-        <select clrSelect name="zoneId" formControlName="zoneId">
+        <select
+            clrSelect
+            name="zoneId"
+            formControlName="zoneId"
+            [attr.disabled]="!('UpdateSettings' | hasPermission)"
+        >
             <option *ngFor="let zone of zones$ | async" [value]="zone.id">{{ zone.name }}</option>
         </select>
     </vdr-form-field>

+ 1 - 1
packages/admin-ui/src/app/settings/components/tax-rate-list/tax-rate-list.component.html

@@ -1,6 +1,6 @@
 <vdr-action-bar>
     <vdr-ab-right>
-        <a class="btn btn-primary" [routerLink]="['./create']">
+        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="'CreateSettings'">
             <clr-icon shape="plus"></clr-icon>
             {{ 'settings.create-new-tax-rate' | translate }}
         </a>

+ 1 - 0
packages/admin-ui/src/i18n-messages/en.json

@@ -518,6 +518,7 @@
     "payment-method-config-options": "Payment method configuration",
     "permissions": "Permissions",
     "prices-include-tax": "Prices include tax for the default Zone",
+    "promotion": "Promotion",
     "rate": "Rate",
     "read": "Read",
     "remove-countries-from-zone": "Remove countries from zone...",