mirror of
https://github.com/valitydev/dashboard.git
synced 2024-11-06 02:25:23 +00:00
OPS-355: Fix roles accesses (#148)
This commit is contained in:
parent
adc9a1a167
commit
452cc3b66d
@ -61,7 +61,9 @@ export function createApi<
|
||||
|
||||
private call(name: keyof T, params: Record<PropertyKey, unknown>) {
|
||||
return this.createExtendedParams().pipe(
|
||||
switchMap((p) => this.api[name](Object.assign({}, params, ...p))),
|
||||
switchMap((extendParams) =>
|
||||
this.api[name](Object.assign({}, ...extendParams, params)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,9 @@
|
||||
*ngFor="let roleId of roleIds"
|
||||
class="dsh-body-2"
|
||||
fxLayoutAlign="center center"
|
||||
>{{ (roleIdDict$ | async)?.[roleId] }}</dsh-nested-table-col
|
||||
><button dsh-button (click)="show(roleId)">
|
||||
{{ (roleIdDict$ | async)?.[roleId] }}
|
||||
</button></dsh-nested-table-col
|
||||
>
|
||||
<dsh-nested-table-col *ngIf="isAllowAdd">
|
||||
<button color="accent" dsh-button (click)="add()">{{ t('add') }}</button>
|
||||
|
@ -6,18 +6,20 @@ import {
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
OnChanges,
|
||||
} from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||
import { MemberRole, ResourceScopeId, RoleId } from '@vality/swag-organizations';
|
||||
import { ComponentChanges } from '@vality/ng-core';
|
||||
import { MemberRole, ResourceScopeId, RoleId, Organization } from '@vality/swag-organizations';
|
||||
import { coerceBoolean } from 'coerce-property';
|
||||
import isNil from 'lodash-es/isNil';
|
||||
import { BehaviorSubject, combineLatest, EMPTY, Observable, of } from 'rxjs';
|
||||
import { first, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { BehaviorSubject, combineLatest, EMPTY, Observable, of, ReplaySubject } from 'rxjs';
|
||||
import { first, map, switchMap, tap, shareReplay } from 'rxjs/operators';
|
||||
|
||||
import { OrganizationsDictionaryService } from '@dsh/app/api/organizations';
|
||||
import { ShopsService } from '@dsh/app/api/payments';
|
||||
import { DialogConfig, DIALOG_CONFIG } from '@dsh/app/sections/tokens';
|
||||
import { ShopsDataService } from '@dsh/app/shared';
|
||||
import { sortRoleIds } from '@dsh/app/shared/components/organization-roles/utils/sort-role-ids';
|
||||
import { PartialReadonly } from '@dsh/type-utils';
|
||||
|
||||
@ -34,7 +36,7 @@ import { SelectRoleDialogData } from './components/select-role-dialog/types/sele
|
||||
templateUrl: 'change-roles-table.component.html',
|
||||
styleUrls: ['change-roles-table.component.scss'],
|
||||
})
|
||||
export class ChangeRolesTableComponent implements OnInit {
|
||||
export class ChangeRolesTableComponent implements OnInit, OnChanges {
|
||||
@Input() set roles(roles: PartialReadonly<MemberRole>[]) {
|
||||
if (!isNil(roles)) {
|
||||
this.roles$.next(roles);
|
||||
@ -44,6 +46,7 @@ export class ChangeRolesTableComponent implements OnInit {
|
||||
get roles(): PartialReadonly<MemberRole>[] {
|
||||
return this.roles$.value;
|
||||
}
|
||||
@Input() organization: Organization;
|
||||
|
||||
/**
|
||||
* Edit mode:
|
||||
@ -57,8 +60,14 @@ export class ChangeRolesTableComponent implements OnInit {
|
||||
@Output() addedRoles = new EventEmitter<PartialReadonly<MemberRole>[]>();
|
||||
@Output() removedRoles = new EventEmitter<PartialReadonly<MemberRole>[]>();
|
||||
|
||||
organization$ = new ReplaySubject<Organization>(1);
|
||||
roleIds: RoleId[] = [];
|
||||
shops$ = this.shopsDataService.shops$;
|
||||
shops$ = this.organization$.pipe(
|
||||
switchMap((organization) =>
|
||||
this.shopsService.getShopsForParty({ partyID: organization.party }),
|
||||
),
|
||||
shareReplay({ bufferSize: 1, refCount: true }),
|
||||
);
|
||||
roleIdDict$ = this.organizationsDictionaryService.roleId$;
|
||||
|
||||
get availableRoles(): RoleId[] {
|
||||
@ -71,20 +80,31 @@ export class ChangeRolesTableComponent implements OnInit {
|
||||
|
||||
roles$ = new BehaviorSubject<PartialReadonly<MemberRole>[]>([]);
|
||||
|
||||
isAllowRemoves$ = this.roles$.pipe(map((r) => r.length > 1));
|
||||
isAllowRemoves$ = this.roles$.pipe(
|
||||
map(
|
||||
(roles) =>
|
||||
!this.editMode || roles.some((r) => roles.some((b) => b.roleId !== r.roleId)),
|
||||
),
|
||||
);
|
||||
|
||||
private get hasAdminRole() {
|
||||
return !!this.roles.find((r) => r.id === RoleId.Administrator);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private shopsDataService: ShopsDataService,
|
||||
private shopsService: ShopsService,
|
||||
private dialog: MatDialog,
|
||||
@Inject(DIALOG_CONFIG) private dialogConfig: DialogConfig,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private organizationsDictionaryService: OrganizationsDictionaryService,
|
||||
) {}
|
||||
|
||||
ngOnChanges({ organization }: ComponentChanges<ChangeRolesTableComponent>) {
|
||||
if (organization) {
|
||||
this.organization$.next(organization.currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.roles$.pipe(untilDestroyed(this)).subscribe((roles) => this.selectedRoles.emit(roles));
|
||||
}
|
||||
@ -116,6 +136,25 @@ export class ChangeRolesTableComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
show(roleId: RoleId) {
|
||||
const removeDialogsClass = addDialogsClass(this.dialog.openDialogs, 'dsh-hidden');
|
||||
this.dialog
|
||||
.open<SelectRoleDialogComponent, SelectRoleDialogData, SelectRoleDialogResult>(
|
||||
SelectRoleDialogComponent,
|
||||
{
|
||||
...this.dialogConfig.large,
|
||||
data: { availableRoles: [roleId], isShow: true },
|
||||
},
|
||||
)
|
||||
.afterClosed()
|
||||
.pipe(untilDestroyed(this))
|
||||
.subscribe({
|
||||
complete: () => {
|
||||
removeDialogsClass();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
remove(roleId: RoleId): void {
|
||||
this.removeRoleIds([roleId]);
|
||||
this.removeRoles(this.roles.filter((r) => r.roleId === roleId));
|
||||
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FlexModule } from '@angular/flex-layout';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { TranslocoModule } from '@ngneat/transloco';
|
||||
@ -26,6 +27,7 @@ import { SelectRoleDialogComponent } from './components/select-role-dialog/selec
|
||||
MatRadioModule,
|
||||
ReactiveFormsModule,
|
||||
SelectionModule,
|
||||
MatButtonModule,
|
||||
],
|
||||
declarations: [ChangeRolesTableComponent, SelectRoleDialogComponent],
|
||||
exports: [ChangeRolesTableComponent],
|
||||
|
@ -5,13 +5,13 @@
|
||||
>
|
||||
<mat-radio-group [formControl]="roleControl">
|
||||
<dsh-nested-table [rowsGridTemplateColumns]="rowsGridTemplateColumns">
|
||||
<dsh-nested-table-row>
|
||||
<dsh-nested-table-row *ngIf="!data.isShow">
|
||||
<dsh-nested-table-col></dsh-nested-table-col>
|
||||
<dsh-nested-table-col *ngFor="let role of roles" fxLayoutAlign="center center">
|
||||
<span class="dsh-body-2 header">{{ (roleIdDict$ | async)?.[role] }}</span>
|
||||
</dsh-nested-table-col>
|
||||
</dsh-nested-table-row>
|
||||
<dsh-nested-table-row>
|
||||
<dsh-nested-table-row *ngIf="!data.isShow">
|
||||
<dsh-nested-table-col></dsh-nested-table-col>
|
||||
<dsh-nested-table-col *ngFor="let role of roles">
|
||||
<mat-radio-button [value]="role"></mat-radio-button>
|
||||
@ -33,7 +33,7 @@
|
||||
</dsh-nested-table-row>
|
||||
</dsh-nested-table>
|
||||
</mat-radio-group>
|
||||
<ng-container dshBaseDialogActions>
|
||||
<ng-container *ngIf="!data.isShow" dshBaseDialogActions>
|
||||
<button [disabled]="roleControl.invalid" color="accent" dsh-button (click)="select()">
|
||||
{{ t('select') }}
|
||||
</button>
|
||||
|
@ -2,4 +2,5 @@ import { RoleId } from '@vality/swag-organizations';
|
||||
|
||||
export interface SelectRoleDialogData {
|
||||
availableRoles: RoleId[];
|
||||
isShow?: boolean;
|
||||
}
|
||||
|
@ -17,7 +17,10 @@
|
||||
<div fxLayout="column" fxLayoutGap="24px">
|
||||
<mat-divider></mat-divider>
|
||||
<h2 class="dsh-title">{{ t('roles') }}</h2>
|
||||
<dsh-change-roles-table (selectedRoles)="selectRoles($event)"></dsh-change-roles-table>
|
||||
<dsh-change-roles-table
|
||||
[organization]="data.organization"
|
||||
(selectedRoles)="selectRoles($event)"
|
||||
></dsh-change-roles-table>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container dshBaseDialogActions>
|
||||
|
@ -37,7 +37,7 @@ export class CreateInvitationDialogComponent {
|
||||
create() {
|
||||
return this.invitationsService
|
||||
.createInvitation({
|
||||
orgId: this.data.orgId,
|
||||
orgId: this.data.organization.id,
|
||||
invitationRequest: {
|
||||
invitee: {
|
||||
contact: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Organization } from '@vality/swag-organizations';
|
||||
|
||||
export type CreateInvitationDialogData = {
|
||||
orgId: Organization['id'];
|
||||
organization: Organization;
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ export class InvitationsComponent {
|
||||
return this.organization$
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap(({ id: orgId }) =>
|
||||
switchMap((organization) =>
|
||||
this.dialog
|
||||
.open<
|
||||
CreateInvitationDialogComponent,
|
||||
@ -51,7 +51,7 @@ export class InvitationsComponent {
|
||||
BaseDialogResponseStatus
|
||||
>(CreateInvitationDialogComponent, {
|
||||
...this.dialogConfig.large,
|
||||
data: { orgId },
|
||||
data: { organization },
|
||||
})
|
||||
.afterClosed(),
|
||||
),
|
||||
|
@ -5,6 +5,7 @@
|
||||
(cancel)="cancel()"
|
||||
>
|
||||
<dsh-change-roles-table
|
||||
[organization]="data.organization"
|
||||
[roles]="roles$ | async"
|
||||
controlled
|
||||
editMode
|
||||
|
@ -21,7 +21,7 @@ export class EditRolesDialogComponent {
|
||||
roles$ = defer(() => this.updateRoles$).pipe(
|
||||
switchMap(() =>
|
||||
this.membersService
|
||||
.getOrgMember({ orgId: this.data.orgId, userId: this.data.userId })
|
||||
.getOrgMember({ orgId: this.data.organization.id, userId: this.data.userId })
|
||||
.pipe(map((r) => r.roles)),
|
||||
),
|
||||
untilDestroyed(this),
|
||||
@ -45,7 +45,7 @@ export class EditRolesDialogComponent {
|
||||
return forkJoin(
|
||||
roles.map((memberRole) =>
|
||||
this.membersService.assignMemberRole({
|
||||
orgId: this.data.orgId,
|
||||
orgId: this.data.organization.id,
|
||||
userId: this.data.userId,
|
||||
memberRole,
|
||||
}),
|
||||
@ -65,7 +65,7 @@ export class EditRolesDialogComponent {
|
||||
roles.map((role) =>
|
||||
this.membersService
|
||||
.removeMemberRole({
|
||||
orgId: this.data.orgId,
|
||||
orgId: this.data.organization.id,
|
||||
userId: this.data.userId,
|
||||
memberRoleId: role.id,
|
||||
})
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Organization } from '@vality/swag-organizations';
|
||||
|
||||
export interface EditRolesDialogData {
|
||||
orgId: string;
|
||||
organization: Organization;
|
||||
userId: string;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ export class MemberComponent implements OnChanges {
|
||||
.open<EditRolesDialogComponent, EditRolesDialogData>(EditRolesDialogComponent, {
|
||||
...this.dialogConfig.large,
|
||||
data: {
|
||||
orgId: this.organization.id,
|
||||
organization: this.organization,
|
||||
userId: this.member.id,
|
||||
},
|
||||
})
|
||||
|
@ -4,16 +4,18 @@
|
||||
fxLayoutGap="32px"
|
||||
>
|
||||
<nav [tabPanel]="tabPanel" mat-tab-nav-bar>
|
||||
<a
|
||||
#rla="routerLinkActive"
|
||||
*ngFor="let link of links"
|
||||
[active]="rla.isActive"
|
||||
[routerLink]="link.path"
|
||||
mat-tab-link
|
||||
routerLinkActive
|
||||
>
|
||||
<span>{{ link.label$ | async }}</span>
|
||||
</a>
|
||||
<ng-container *ngFor="let link of links">
|
||||
<a
|
||||
#rla="routerLinkActive"
|
||||
*ngIf="link.roles | isAccessAllowed: 'some'"
|
||||
[active]="rla.isActive"
|
||||
[routerLink]="link.path"
|
||||
mat-tab-link
|
||||
routerLinkActive
|
||||
>
|
||||
<span>{{ link.label$ | async }}</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</nav>
|
||||
<mat-tab-nav-panel #tabPanel>
|
||||
<router-outlet></router-outlet>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { TranslocoService } from '@ngneat/transloco';
|
||||
|
||||
import { RoleAccessName } from '@dsh/app/auth';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'integrations.component.html',
|
||||
})
|
||||
@ -13,6 +15,7 @@ export class IntegrationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.PaymentLinks],
|
||||
},
|
||||
{
|
||||
path: 'api-keys',
|
||||
@ -21,6 +24,7 @@ export class IntegrationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.ApiKeys],
|
||||
},
|
||||
{
|
||||
path: 'webhooks',
|
||||
@ -29,6 +33,7 @@ export class IntegrationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.Webhooks],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { FlexModule } from '@angular/flex-layout';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { TranslocoModule } from '@ngneat/transloco';
|
||||
|
||||
import { AuthModule } from '@dsh/app/auth';
|
||||
import { LayoutModule } from '@dsh/components/layout';
|
||||
import { ScrollUpModule } from '@dsh/components/navigation';
|
||||
|
||||
@ -19,6 +20,7 @@ import { IntegrationsComponent } from './integrations.component';
|
||||
TranslocoModule,
|
||||
ScrollUpModule,
|
||||
MatTabsModule,
|
||||
AuthModule,
|
||||
],
|
||||
declarations: [IntegrationsComponent],
|
||||
})
|
||||
|
@ -5,16 +5,18 @@
|
||||
fxLayoutGap="32px"
|
||||
>
|
||||
<nav mat-tab-nav-bar>
|
||||
<a
|
||||
#rla="routerLinkActive"
|
||||
*ngFor="let link of links"
|
||||
[active]="rla.isActive"
|
||||
[routerLink]="link.path"
|
||||
mat-tab-link
|
||||
routerLinkActive
|
||||
>
|
||||
<span>{{ link.label$ | async }}</span>
|
||||
</a>
|
||||
<ng-container *ngFor="let link of links">
|
||||
<a
|
||||
#rla="routerLinkActive"
|
||||
*ngIf="link.roles | isAccessAllowed: 'some'"
|
||||
[active]="rla.isActive"
|
||||
[routerLink]="link.path"
|
||||
mat-tab-link
|
||||
routerLinkActive
|
||||
>
|
||||
<span>{{ link.label$ | async }}</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</nav>
|
||||
<div>
|
||||
<router-outlet></router-outlet>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { TranslocoService } from '@ngneat/transloco';
|
||||
|
||||
import { RoleAccessName } from '@dsh/app/auth';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'operations.component.html',
|
||||
})
|
||||
@ -13,6 +15,7 @@ export class OperationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.ViewPayments],
|
||||
},
|
||||
{
|
||||
path: 'invoices',
|
||||
@ -21,6 +24,7 @@ export class OperationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.ViewInvoices],
|
||||
},
|
||||
{
|
||||
path: 'refunds',
|
||||
@ -29,6 +33,7 @@ export class OperationsComponent {
|
||||
null,
|
||||
'payment-section',
|
||||
),
|
||||
roles: [RoleAccessName.ViewRefunds],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { TranslocoModule } from '@ngneat/transloco';
|
||||
|
||||
import { AuthModule } from '@dsh/app/auth';
|
||||
import { LayoutModule } from '@dsh/components/layout';
|
||||
import { ScrollUpModule } from '@dsh/components/navigation';
|
||||
|
||||
@ -19,6 +20,7 @@ import { OperationsComponent } from './operations.component';
|
||||
TranslocoModule,
|
||||
ScrollUpModule,
|
||||
MatTabsModule,
|
||||
AuthModule,
|
||||
],
|
||||
declarations: [OperationsComponent],
|
||||
})
|
||||
|
@ -31,11 +31,18 @@ const PAYMENT_SECTION_ROUTES: Routes = [
|
||||
},
|
||||
[RoleAccessName.ViewAnalytics],
|
||||
),
|
||||
{
|
||||
path: 'operations',
|
||||
loadChildren: () =>
|
||||
import('./operations/operations.module').then((m) => m.OperationsModule),
|
||||
},
|
||||
createPrivateRoute(
|
||||
{
|
||||
path: 'operations',
|
||||
loadChildren: () =>
|
||||
import('./operations/operations.module').then((m) => m.OperationsModule),
|
||||
},
|
||||
[
|
||||
RoleAccessName.ViewPayments,
|
||||
RoleAccessName.ViewInvoices,
|
||||
RoleAccessName.ViewRefunds,
|
||||
],
|
||||
),
|
||||
createPrivateRoute(
|
||||
{
|
||||
path: 'reports',
|
||||
@ -51,11 +58,16 @@ const PAYMENT_SECTION_ROUTES: Routes = [
|
||||
// },
|
||||
// [RoleAccessName.ViewPayouts]
|
||||
// ),
|
||||
{
|
||||
path: 'integrations',
|
||||
loadChildren: () =>
|
||||
import('./integrations/integrations.module').then((m) => m.IntegrationsModule),
|
||||
},
|
||||
createPrivateRoute(
|
||||
{
|
||||
path: 'integrations',
|
||||
loadChildren: () =>
|
||||
import('./integrations/integrations.module').then(
|
||||
(m) => m.IntegrationsModule,
|
||||
),
|
||||
},
|
||||
[RoleAccessName.PaymentLinks, RoleAccessName.ApiKeys, RoleAccessName.Webhooks],
|
||||
),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
@ -3,7 +3,13 @@
|
||||
fxLayout="column"
|
||||
fxLayoutGap="32px"
|
||||
>
|
||||
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="end" fxLayoutGap="16px">
|
||||
<div
|
||||
*ngIf="'Claims' | isAccessAllowed"
|
||||
fxLayout="column"
|
||||
fxLayout.gt-sm="row"
|
||||
fxLayoutAlign="end"
|
||||
fxLayoutGap="16px"
|
||||
>
|
||||
<button color="accent" dsh-button (click)="createShop()">{{ t('createShop') }}</button>
|
||||
</div>
|
||||
<dsh-shops-list
|
||||
|
@ -4,6 +4,7 @@ import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslocoModule } from '@ngneat/transloco';
|
||||
|
||||
import { AuthModule } from '@dsh/app/auth';
|
||||
import { ShopCreationModule } from '@dsh/app/shared/components/shop-creation';
|
||||
import { ButtonModule } from '@dsh/components/buttons';
|
||||
|
||||
@ -26,6 +27,7 @@ import { ShopsComponent } from './shops.component';
|
||||
ShopCreationModule,
|
||||
ButtonModule,
|
||||
TranslocoModule,
|
||||
AuthModule,
|
||||
],
|
||||
declarations: [ShopsComponent],
|
||||
exports: [ShopsComponent],
|
||||
|
@ -59,7 +59,7 @@ export const toNavbarItemConfig = ({
|
||||
routerLink: NavbarRouterLink.Reports,
|
||||
icon: BootstrapIconName.FileText,
|
||||
label: reports,
|
||||
roles: [],
|
||||
roles: [RoleAccessName.Reports],
|
||||
},
|
||||
{
|
||||
routerLink: NavbarRouterLink.Integrations,
|
||||
|
@ -5,7 +5,7 @@ import { map, pluck, shareReplay, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { MembersService } from '@dsh/app/api/organizations';
|
||||
import { SHARE_REPLAY_CONF } from '@dsh/app/custom-operators';
|
||||
import { ContextOrganizationService } from '@dsh/app/shared';
|
||||
import { KeycloakTokenInfoService } from '@dsh/app/shared';
|
||||
import { Initializable } from '@dsh/app/shared/types';
|
||||
|
||||
@Injectable()
|
||||
@ -16,16 +16,19 @@ export class OrganizationManagementService implements Initializable {
|
||||
shareReplay(SHARE_REPLAY_CONF),
|
||||
);
|
||||
isOrganizationOwner$: Observable<boolean> = defer(() =>
|
||||
combineLatest([
|
||||
this.organization$,
|
||||
this.contextOrganizationService.organization$.pipe(pluck('party')),
|
||||
]),
|
||||
combineLatest([this.organization$, this.keycloakTokenInfoService.userID$]),
|
||||
).pipe(
|
||||
map(([{ owner }, id]) => owner === id),
|
||||
shareReplay(SHARE_REPLAY_CONF),
|
||||
);
|
||||
isOrganizationAdmin$: Observable<boolean> = this.contextOrganizationService.member$.pipe(
|
||||
map((member) => member.roles.findIndex((r) => r.roleId === RoleId.Administrator) !== -1),
|
||||
isOrganizationAdmin$: Observable<boolean> = combineLatest([
|
||||
this.members$,
|
||||
this.keycloakTokenInfoService.userID$,
|
||||
]).pipe(
|
||||
map(([members, userId]) => members.find((m) => m.id === userId)),
|
||||
map(
|
||||
(member) => member?.roles?.findIndex?.((r) => r.roleId === RoleId.Administrator) !== -1,
|
||||
),
|
||||
shareReplay(SHARE_REPLAY_CONF),
|
||||
);
|
||||
hasAdminAccess$: Observable<boolean> = defer(() =>
|
||||
@ -39,7 +42,7 @@ export class OrganizationManagementService implements Initializable {
|
||||
|
||||
constructor(
|
||||
private membersService: MembersService,
|
||||
private contextOrganizationService: ContextOrganizationService,
|
||||
private keycloakTokenInfoService: KeycloakTokenInfoService,
|
||||
) {}
|
||||
|
||||
init(organization: Organization) {
|
||||
|
@ -115,7 +115,7 @@
|
||||
"manageWebhooks": "Manage webhooks",
|
||||
"payments": "Payments",
|
||||
"viewAnalytics": "View analytics",
|
||||
"viewApiKey": "View the API key",
|
||||
"viewApiKey": "View API keys",
|
||||
"viewInvoices": "View invoices",
|
||||
"viewPayments": "View payments",
|
||||
"viewPayouts": "View payouts",
|
||||
|
@ -115,7 +115,7 @@
|
||||
"manageWebhooks": "Управление Webhooks",
|
||||
"payments": "Платежи",
|
||||
"viewAnalytics": "Просмотр аналитики",
|
||||
"viewApiKey": "Просмотр API ключа",
|
||||
"viewApiKey": "Просмотр API ключей",
|
||||
"viewInvoices": "Просмотр инвойсов",
|
||||
"viewPayments": "Просмотр платежей",
|
||||
"viewPayouts": "Просмотр возмещений",
|
||||
|
Loading…
Reference in New Issue
Block a user