tenant configuration changes
This commit is contained in:
parent
7ea32faa94
commit
8d20ff57e9
|
@ -65,6 +65,15 @@
|
||||||
<app-tenant-configuration-logo-editor></app-tenant-configuration-logo-editor>
|
<app-tenant-configuration-logo-editor></app-tenant-configuration-logo-editor>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
<mat-expansion-panel>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>{{'TENANT-CONFIGURATION-EDITOR.NOTIFIER-LIST.TITLE' | translate}}</mat-panel-title>
|
||||||
|
<mat-panel-description>{{'TENANT-CONFIGURATION-EDITOR.NOTIFIER-LIST.HINT' | translate}}</mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<ng-template matExpansionPanelContent>
|
||||||
|
<app-tenant-configuration-notifier-list-editor></app-tenant-configuration-notifier-list-editor>
|
||||||
|
</ng-template>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
|
||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { DepositEditorComponent } from './editor/deposit/deposit-editor.componen
|
||||||
import { FileTransformerEditorComponent } from './editor/file-transformer/file-transformer-editor.component';
|
import { FileTransformerEditorComponent } from './editor/file-transformer/file-transformer-editor.component';
|
||||||
import { LogoEditorComponent } from './editor/logo/logo-editor.component';
|
import { LogoEditorComponent } from './editor/logo/logo-editor.component';
|
||||||
import { NgxColorsModule } from 'ngx-colors';
|
import { NgxColorsModule } from 'ngx-colors';
|
||||||
|
import { NotifierListModule } from '@notification-service/ui/admin/tenant-configuration/notifier-list/notifier-list-editor.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -35,7 +36,8 @@ import { NgxColorsModule } from 'ngx-colors';
|
||||||
UserSettingsModule,
|
UserSettingsModule,
|
||||||
CommonFormattingModule,
|
CommonFormattingModule,
|
||||||
RichTextEditorModule,
|
RichTextEditorModule,
|
||||||
NgxColorsModule
|
NgxColorsModule,
|
||||||
|
NotifierListModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
TenantConfigurationEditorComponent,
|
TenantConfigurationEditorComponent,
|
||||||
|
|
|
@ -316,6 +316,10 @@
|
||||||
"TITLE": "Extra Logo",
|
"TITLE": "Extra Logo",
|
||||||
"HINT": "Add extra logo"
|
"HINT": "Add extra logo"
|
||||||
},
|
},
|
||||||
|
"NOTIFIER-LIST":{
|
||||||
|
"TITLE": "Notification Preferences",
|
||||||
|
"HINT": "Select available notifiers for Notification Types"
|
||||||
|
},
|
||||||
"DEPOSIT-PLUGINS":{
|
"DEPOSIT-PLUGINS":{
|
||||||
"TITLE": "Deposit Plugins",
|
"TITLE": "Deposit Plugins",
|
||||||
"HINT": "Change deposit plugins"
|
"HINT": "Change deposit plugins"
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum TenantConfigurationType {
|
||||||
|
NotifierList = 0,
|
||||||
|
DefaultUserLocale = 1,
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model";
|
||||||
|
import { TenantConfigurationType } from "@notification-service/core/enum/tenant-configuration-type";
|
||||||
|
import { NotificationContactType } from "@notification-service/core/enum/notification-contact-type";
|
||||||
|
|
||||||
|
export interface TenantConfiguration extends BaseEntity{
|
||||||
|
type?: TenantConfigurationType;
|
||||||
|
notifierList?: NotifierListTenantConfiguration;
|
||||||
|
defaultUserLocale?: DefaultUserLocaleTenantConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotifierListTenantConfiguration{
|
||||||
|
notifiers: { [key: string]: NotificationContactType[] };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DefaultUserLocaleTenantConfiguration{
|
||||||
|
timezone: string;
|
||||||
|
language: string;
|
||||||
|
culture: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//persist
|
||||||
|
|
||||||
|
export interface TenantConfigurationPersist extends BaseEntityPersist{
|
||||||
|
type: TenantConfigurationType;
|
||||||
|
notifierList?: NotifierListTenantConfigurationPersist;
|
||||||
|
defaultUserLocale?: DefaultUserLocaleTenantConfigurationPersist;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotifierListTenantConfigurationPersist{
|
||||||
|
notifiers: { [key: string]: NotificationContactType[] };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DefaultUserLocaleTenantConfigurationPersist{
|
||||||
|
timezone: string;
|
||||||
|
language: string;
|
||||||
|
culture: string;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Lookup } from '@common/model/lookup';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { TenantConfigurationType } from '../enum/tenant-configuration-type';
|
||||||
|
import { IsActive } from '../enum/is-active.enum';
|
||||||
|
|
||||||
|
export class TenantConfigurationLookup extends Lookup implements TenantConfigurationFilter {
|
||||||
|
ids: Guid[];
|
||||||
|
excludedIds: Guid[];
|
||||||
|
types: TenantConfigurationType[];
|
||||||
|
isActive: IsActive[];
|
||||||
|
tenantIds: Guid[];
|
||||||
|
tenantIsSet: boolean;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationFilter {
|
||||||
|
ids: Guid[];
|
||||||
|
excludedIds: Guid[];
|
||||||
|
types: TenantConfigurationType[];
|
||||||
|
tenantIds: Guid[];
|
||||||
|
tenantIsSet: boolean;
|
||||||
|
isActive: IsActive[];
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { QueryResult } from '@common/model/query-result';
|
||||||
|
import { FilterService } from '@common/modules/text-filter/filter-service';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { Observable, throwError } from 'rxjs';
|
||||||
|
import { catchError } from 'rxjs/operators';
|
||||||
|
import { BaseHttpV2Service } from '@app/core/services/http/base-http-v2.service';
|
||||||
|
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
|
||||||
|
import { TenantConfigurationLookup } from '@notification-service/core/query/tenant-configuration.lookup';
|
||||||
|
import { TenantConfiguration, TenantConfigurationPersist } from '@notification-service/core/model/tenant-configuration';
|
||||||
|
import { TenantConfigurationType } from '@notification-service/core/enum/tenant-configuration-type';
|
||||||
|
import { NotifierListLookup } from '@notification-service/core/query/notifier-list.lookup';
|
||||||
|
import { NotifierListConfigurationDataContainer } from '@notification-service/core/model/notifier-configuration.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TenantConfigurationService {
|
||||||
|
|
||||||
|
constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService, private filterService: FilterService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private get apiBase(): string { return `${this.configurationService.notificationServiceAddress}api/notification/tenant-configuration`; }
|
||||||
|
|
||||||
|
query(q: TenantConfigurationLookup): Observable<QueryResult<TenantConfiguration>> {
|
||||||
|
const url = `${this.apiBase}/query`;
|
||||||
|
return this.http.post<QueryResult<TenantConfiguration>>(url, q).pipe(catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
getSingle(id: Guid, reqFields: string[] = []): Observable<TenantConfiguration> {
|
||||||
|
const url = `${this.apiBase}/${id}`;
|
||||||
|
const options = { params: { f: reqFields } };
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<TenantConfiguration>(url, options).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentTenantType(type: TenantConfigurationType, reqFields: string[] = []): Observable<TenantConfiguration> {
|
||||||
|
const url = `${this.apiBase}/current-tenant/${type}`;
|
||||||
|
const options = { params: { f: reqFields } };
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<TenantConfiguration>(url, options).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
persist(item: TenantConfigurationPersist): Observable<TenantConfiguration> {
|
||||||
|
const url = `${this.apiBase}/persist`;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post<TenantConfiguration>(url, item).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: Guid): Observable<void> {
|
||||||
|
const url = `${this.apiBase}/${id}`;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.delete<void>(url).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
getNotifierList(q: NotifierListLookup): Observable<NotifierListConfigurationDataContainer> {
|
||||||
|
const url = `${this.apiBase}/notifier-list/available`;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post<NotifierListConfigurationDataContainer>(url, q).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<div *ngIf="formGroup" class="container-fluid notifier-list ">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12" *ngFor="let notificationType of availableNotifiersKeys">
|
||||||
|
<div class="row">
|
||||||
|
<mat-selection-list class="col-12" [formControl]="formGroup.get('notifierList')?.get('notifiers')?.get(notificationType)" cdkDropList (cdkDropListDropped)="dropped($event, notificationType)">
|
||||||
|
<h3 mat-subheader>{{notificationServiceEnumUtils.toNotificationTypeString(notificationType)}}</h3>
|
||||||
|
<mat-list-option *ngFor="let contactType of availableNotifiers[notificationType]" [value]="contactType" cdkDrag>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<mat-icon matListIcon cdkDragHandle>unfold_more</mat-icon>
|
||||||
|
{{notificationServiceEnumUtils.toContactTypeString(contactType)}}
|
||||||
|
</div>
|
||||||
|
</mat-list-option>
|
||||||
|
</mat-selection-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row actions-row">
|
||||||
|
<div class="ml-auto col-auto" *ngIf="editorModel.id"><button class="normal-btn-sm" (click)="delete()">
|
||||||
|
{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.RESET-TO-DEFAULT' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="ml-auto col-auto"><button class="normal-btn-sm" (click)="formSubmit()">
|
||||||
|
{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.SAVE' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
.notifier-list {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||||
|
import { FormGroup, UntypedFormGroup } from '@angular/forms';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
|
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||||
|
import { LoggingService } from '@app/core/services/logging/logging-service';
|
||||||
|
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||||
|
import { BasePendingChangesComponent } from '@common/base/base-pending-changes.component';
|
||||||
|
import { FormService } from '@common/forms/form-service';
|
||||||
|
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { NotificationContactType } from '@notification-service/core/enum/notification-contact-type';
|
||||||
|
import { NotificationTrackingProcess } from '@notification-service/core/enum/notification-tracking-process.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service';
|
||||||
|
import { UserNotificationPreference } from '@notification-service/core/model/user-notification-preference.model';
|
||||||
|
import { NotifierListLookup } from '@notification-service/core/query/notifier-list.lookup';
|
||||||
|
import { UserNotificationPreferenceService } from '@notification-service/services/http/user-notification-preference.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
|
import { nameof } from 'ts-simple-nameof';
|
||||||
|
import { TenantConfigurationEditorModel } from './notifier-list-editor.model';
|
||||||
|
import { TenantConfiguration, TenantConfigurationPersist } from '@notification-service/core/model/tenant-configuration';
|
||||||
|
import { TenantConfigurationService } from '@notification-service/services/http/tenant-configuration.service';
|
||||||
|
import { TenantConfigurationType } from '@notification-service/core/enum/tenant-configuration-type';
|
||||||
|
import { NotifierListEditorResolver } from './notifier-list-editor.resolver';
|
||||||
|
import { ResponseErrorCode } from '@app/core/common/enum/respone-error-code';
|
||||||
|
import { NotifierListEditorService } from './notifier-list-editor.service';
|
||||||
|
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tenant-configuration-notifier-list-editor',
|
||||||
|
templateUrl: './notifier-list-editor.component.html',
|
||||||
|
styleUrls: ['./notifier-list-editor.component.scss'],
|
||||||
|
providers: [NotifierListEditorService]
|
||||||
|
})
|
||||||
|
export class NotifierListEditorComponent extends BasePendingChangesComponent implements OnInit {
|
||||||
|
|
||||||
|
availableNotifiers: { [key: string]: NotificationContactType[] } = {};
|
||||||
|
availableNotifiersKeys: NotificationType[];
|
||||||
|
|
||||||
|
get editorModel(): TenantConfigurationEditorModel { return this._editorModel; }
|
||||||
|
set editorModel(value: TenantConfigurationEditorModel) { this._editorModel = value; }
|
||||||
|
private _editorModel: TenantConfigurationEditorModel;
|
||||||
|
|
||||||
|
notificationTrackingProcess: NotificationTrackingProcess = NotificationTrackingProcess.PENDING;
|
||||||
|
|
||||||
|
isNew = true;
|
||||||
|
formGroup: UntypedFormGroup = null;
|
||||||
|
|
||||||
|
protected get canDelete(): boolean {
|
||||||
|
return !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteTenantConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get canSave(): boolean {
|
||||||
|
return this.hasPermission(this.authService.permissionEnum.EditTenantConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasPermission(permission: AppPermission): boolean {
|
||||||
|
return this.authService.hasPermission(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected dialog: MatDialog,
|
||||||
|
private uiNotificationService: UiNotificationService,
|
||||||
|
private language: TranslateService,
|
||||||
|
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||||
|
private authService: AuthService,
|
||||||
|
protected formService: FormService,
|
||||||
|
private logger: LoggingService,
|
||||||
|
private tenantConfigurationService: TenantConfigurationService,
|
||||||
|
public notificationServiceEnumUtils: NotificationServiceEnumUtils,
|
||||||
|
public notifierListEditorService: NotifierListEditorService
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
canDeactivate(): boolean | Observable<boolean> {
|
||||||
|
return this.formGroup ? !this.formGroup.dirty : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfiguration() {
|
||||||
|
this.formGroup = null;
|
||||||
|
this.tenantConfigurationService.getNotifierList(new NotifierListLookup())
|
||||||
|
.pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
data => {
|
||||||
|
try {
|
||||||
|
this.availableNotifiers = data.notifiers;
|
||||||
|
this.availableNotifiersKeys = Object.keys(this.availableNotifiers) as NotificationType[];
|
||||||
|
this.getExistingSelections();
|
||||||
|
} catch {
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.ERROR;
|
||||||
|
this.logger.error('Could not parse Dataset: ' + data);
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getExistingSelections() {
|
||||||
|
this.tenantConfigurationService.getCurrentTenantType(TenantConfigurationType.NotifierList, NotifierListEditorResolver.lookupFields())
|
||||||
|
.pipe(takeUntil(this._destroyed)).subscribe(
|
||||||
|
data => {
|
||||||
|
try {
|
||||||
|
if (data?.notifierList?.notifiers) {
|
||||||
|
this.orderAvailableItemsbasedOnExistingSelections(data);
|
||||||
|
}
|
||||||
|
this.editorModel = data?.notifierList?.notifiers ? new TenantConfigurationEditorModel().fromModel(data) : new TenantConfigurationEditorModel();
|
||||||
|
this.buildForm();
|
||||||
|
} catch {
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.ERROR;
|
||||||
|
this.logger.error('Could not parse Dataset: ' + data);
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
orderAvailableItemsbasedOnExistingSelections(existingSelections: TenantConfiguration) {
|
||||||
|
if (!existingSelections?.notifierList?.notifiers) { return; }
|
||||||
|
this.availableNotifiersKeys.forEach(key => {
|
||||||
|
const orderedList = [];
|
||||||
|
orderedList.push(...(existingSelections.notifierList.notifiers[key] || []).filter(x => this.availableNotifiers[key].includes(x))); // First push the selected ordered values.
|
||||||
|
orderedList.push(...this.availableNotifiers[key].filter(x => !orderedList.includes(x))); //Then push the rest items.
|
||||||
|
this.availableNotifiers[key] = orderedList;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dropped(event: CdkDragDrop<string[]>, type: NotificationType) {
|
||||||
|
moveItemInArray(this.availableNotifiers[type], event.previousIndex, event.currentIndex);
|
||||||
|
}
|
||||||
|
onCallbackError(errorResponse: HttpErrorResponse) {
|
||||||
|
|
||||||
|
console.log("Error:", errorResponse);
|
||||||
|
|
||||||
|
const error: HttpError = this.httpErrorHandlingService.getError(errorResponse);
|
||||||
|
if (error.statusCode === 400) {
|
||||||
|
this.editorModel.validationErrorModel.fromJSONObject(errorResponse.error);
|
||||||
|
if(errorResponse.error.code === ResponseErrorCode.TenantConfigurationTypeCanNotChange){
|
||||||
|
this.uiNotificationService.snackBarNotification(errorResponse.error.error, SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
if(errorResponse.error.code === ResponseErrorCode.MultipleTenantConfigurationTypeNotAllowed){
|
||||||
|
this.uiNotificationService.snackBarNotification(errorResponse.error.error, SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
this.formService.validateAllFormFields(this.formGroup);
|
||||||
|
} else {
|
||||||
|
this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onCallbackSuccess(data?: any): void {
|
||||||
|
|
||||||
|
console.log("Success:", data);
|
||||||
|
|
||||||
|
this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
|
||||||
|
this.refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
prepareForm(data: TenantConfiguration) {
|
||||||
|
try {
|
||||||
|
this.editorModel = data ? new TenantConfigurationEditorModel().fromModel(data) : new TenantConfigurationEditorModel();
|
||||||
|
this.buildForm();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('Could not parse TenantConfiguration item: ' + data + error);
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm() {
|
||||||
|
this.formGroup = this.editorModel.buildForm(this.availableNotifiersKeys, this.availableNotifiers, null, !this.authService.hasPermission(AppPermission.EditTenantConfiguration));
|
||||||
|
this.notifierListEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshData(): void {
|
||||||
|
this.getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
persistEntity(onSuccess?: (response) => void): void {
|
||||||
|
const formData = this.formService.getValue(this.formGroup.value) as TenantConfigurationPersist;
|
||||||
|
|
||||||
|
// Clear empty or null selections.
|
||||||
|
if (formData?.notifierList?.notifiers) {
|
||||||
|
Object.keys(formData.notifierList.notifiers).forEach(key => {
|
||||||
|
if (formData.notifierList.notifiers[key] == null || formData.notifierList.notifiers[key].length === 0) { delete formData.notifierList.notifiers[key]; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.tenantConfigurationService.persist(formData)
|
||||||
|
.pipe(takeUntil(this._destroyed)).subscribe(
|
||||||
|
complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete),
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
formSubmit(): void {
|
||||||
|
this.clearErrorModel();
|
||||||
|
this.formService.removeAllBackEndErrors(this.formGroup);
|
||||||
|
this.formService.touchAllFormFields(this.formGroup);
|
||||||
|
if (!this.isFormValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.persistEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public isFormValid() {
|
||||||
|
return this.formGroup.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete() {
|
||||||
|
const value = this.formGroup.value;
|
||||||
|
if (value.id) {
|
||||||
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
|
maxWidth: '300px',
|
||||||
|
data: {
|
||||||
|
message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
|
||||||
|
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
|
||||||
|
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
this.tenantConfigurationService.delete(value.id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
complete => this.onCallbackDeleteSuccessConfig(),
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCallbackDeleteSuccessConfig(data?: any): void {
|
||||||
|
|
||||||
|
console.log("Success Delete:", data);
|
||||||
|
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-RESET'), SnackBarNotificationLevel.Success);
|
||||||
|
this.prepareForm(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clearErrorModel() {
|
||||||
|
this.editorModel.validationErrorModel.clear();
|
||||||
|
this.formService.validateAllFormFields(this.formGroup);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
import { FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
|
||||||
|
import { BaseEditorModel } from "@common/base/base-form-editor-model";
|
||||||
|
import { BackendErrorValidator } from "@common/forms/validation/custom-validator";
|
||||||
|
import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model";
|
||||||
|
import { Validation, ValidationContext } from "@common/forms/validation/validation-context";
|
||||||
|
import { NotificationContactType } from "@notification-service/core/enum/notification-contact-type";
|
||||||
|
import { NotificationType } from "@notification-service/core/enum/notification-type.enum";
|
||||||
|
import { TenantConfigurationType } from "@notification-service/core/enum/tenant-configuration-type";
|
||||||
|
import { NotifierListTenantConfiguration, NotifierListTenantConfigurationPersist, TenantConfiguration, TenantConfigurationPersist } from "@notification-service/core/model/tenant-configuration";
|
||||||
|
|
||||||
|
export class TenantConfigurationEditorModel extends BaseEditorModel implements TenantConfigurationPersist {
|
||||||
|
type: TenantConfigurationType;
|
||||||
|
notifierList: NotifierListTenantConfigurationEditorModel = new NotifierListTenantConfigurationEditorModel(this.validationErrorModel);
|
||||||
|
|
||||||
|
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
||||||
|
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
|
||||||
|
|
||||||
|
constructor() { super(); this.type = TenantConfigurationType.NotifierList; }
|
||||||
|
|
||||||
|
public fromModel(item: TenantConfiguration): TenantConfigurationEditorModel {
|
||||||
|
if (item) {
|
||||||
|
super.fromModel(item);
|
||||||
|
this.type = item.type;
|
||||||
|
if (item.notifierList) this.notifierList = new NotifierListTenantConfigurationEditorModel(this.validationErrorModel).fromModel(item.notifierList);
|
||||||
|
} else {
|
||||||
|
this.type = TenantConfigurationType.NotifierList;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm(availableNotificationTypes: NotificationType[], availableNotifiers: { [key: string]: NotificationContactType[] }, context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup {
|
||||||
|
if (context == null) { context = this.createValidationContext(); }
|
||||||
|
|
||||||
|
return this.formBuilder.group({
|
||||||
|
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
|
||||||
|
type: [{ value: this.type, disabled: disabled }, context.getValidation('type').validators],
|
||||||
|
hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators],
|
||||||
|
notifierList: this.notifierList.buildForm({
|
||||||
|
availableNotificationTypes: availableNotificationTypes,
|
||||||
|
availableNotifiers: availableNotifiers,
|
||||||
|
rootPath: `NotifierList.`,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createValidationContext(): ValidationContext {
|
||||||
|
const baseContext: ValidationContext = new ValidationContext();
|
||||||
|
const baseValidationArray: Validation[] = new Array<Validation>();
|
||||||
|
baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
|
||||||
|
baseValidationArray.push({ key: 'type', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'type')] });
|
||||||
|
baseValidationArray.push({ key: 'hash', validators: [] });
|
||||||
|
|
||||||
|
baseContext.validation = baseValidationArray;
|
||||||
|
return baseContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotifierListTenantConfigurationEditorModel implements NotifierListTenantConfigurationPersist {
|
||||||
|
notifiers: { [key: string]: NotificationContactType[] };
|
||||||
|
|
||||||
|
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel()
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public fromModel(item: NotifierListTenantConfiguration): NotifierListTenantConfigurationEditorModel {
|
||||||
|
if (item) {
|
||||||
|
this.notifiers = item.notifiers;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm(params?: {
|
||||||
|
availableNotificationTypes: NotificationType[],
|
||||||
|
availableNotifiers: { [key: string]: NotificationContactType[] };
|
||||||
|
context?: ValidationContext,
|
||||||
|
disabled?: boolean,
|
||||||
|
rootPath?: string
|
||||||
|
}): UntypedFormGroup {
|
||||||
|
let { context = null, disabled = false, rootPath } = params ?? {}
|
||||||
|
if (context == null) {
|
||||||
|
context = NotifierListTenantConfigurationEditorModel.createValidationContext({
|
||||||
|
validationErrorModel: this.validationErrorModel,
|
||||||
|
rootPath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const notifiersFormGroup = this.formBuilder.group({});
|
||||||
|
if (params?.availableNotificationTypes) {
|
||||||
|
params.availableNotificationTypes.forEach(type => {
|
||||||
|
notifiersFormGroup.addControl(type, new FormControl(this.notifiers ? this.notifiers[type] : (params.availableNotifiers ? params.availableNotifiers[type] : undefined)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const form: UntypedFormGroup = this.formBuilder.group({
|
||||||
|
notifiers: notifiersFormGroup,
|
||||||
|
});
|
||||||
|
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static createValidationContext(params: {
|
||||||
|
rootPath?: string,
|
||||||
|
validationErrorModel: ValidationErrorModel
|
||||||
|
}): ValidationContext {
|
||||||
|
const { rootPath = '', validationErrorModel } = params;
|
||||||
|
|
||||||
|
const baseContext: ValidationContext = new ValidationContext();
|
||||||
|
const baseValidationArray: Validation[] = new Array<Validation>();
|
||||||
|
baseValidationArray.push({ key: 'notifiers', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}notifiers`)] });
|
||||||
|
|
||||||
|
baseContext.validation = baseValidationArray;
|
||||||
|
return baseContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||||
|
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||||
|
import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module';
|
||||||
|
// import { TotpModule } from '@idp-service/ui/totp/totp.module';
|
||||||
|
import { NotifierListEditorComponent } from './notifier-list-editor.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonUiModule,
|
||||||
|
CommonFormsModule,
|
||||||
|
DragDropModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
NotifierListEditorComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
NotifierListEditorComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NotifierListModule { }
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service';
|
||||||
|
import { BaseEditorResolver } from '@common/base/base-editor.resolver';
|
||||||
|
import { TenantConfigurationType } from '@notification-service/core/enum/tenant-configuration-type';
|
||||||
|
import { NotifierListTenantConfiguration, TenantConfiguration } from '@notification-service/core/model/tenant-configuration';
|
||||||
|
import { TenantConfigurationService } from '@notification-service/services/http/tenant-configuration.service';
|
||||||
|
import { takeUntil, tap } from 'rxjs/operators';
|
||||||
|
import { nameof } from 'ts-simple-nameof';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NotifierListEditorResolver extends BaseEditorResolver {
|
||||||
|
|
||||||
|
constructor(private tenantConfigurationService: TenantConfigurationService, private breadcrumbService: BreadcrumbService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static lookupFields(): string[] {
|
||||||
|
return [
|
||||||
|
...BaseEditorResolver.lookupFields(),
|
||||||
|
nameof<TenantConfiguration>(x => x.id),
|
||||||
|
nameof<TenantConfiguration>(x => x.type),
|
||||||
|
nameof<TenantConfiguration>(x => x.notifierList),
|
||||||
|
|
||||||
|
[nameof<TenantConfiguration>(x => x.notifierList), nameof<NotifierListTenantConfiguration>(x => x.notifiers)].join('.'),
|
||||||
|
|
||||||
|
|
||||||
|
nameof<TenantConfiguration>(x => x.createdAt),
|
||||||
|
nameof<TenantConfiguration>(x => x.updatedAt),
|
||||||
|
nameof<TenantConfiguration>(x => x.hash),
|
||||||
|
nameof<TenantConfiguration>(x => x.isActive)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve() {
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
...NotifierListEditorResolver.lookupFields()
|
||||||
|
];
|
||||||
|
|
||||||
|
return this.tenantConfigurationService.getCurrentTenantType(TenantConfigurationType.NotifierList, fields).pipe(takeUntil(this._destroyed));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NotifierListEditorService {
|
||||||
|
private validationErrorModel: ValidationErrorModel;
|
||||||
|
|
||||||
|
public setValidationErrorModel(validationErrorModel: ValidationErrorModel): void {
|
||||||
|
this.validationErrorModel = validationErrorModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValidationErrorModel(): ValidationErrorModel {
|
||||||
|
return this.validationErrorModel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ import gr.cite.notification.model.builder.tenantconfiguration.TenantConfiguratio
|
||||||
import gr.cite.notification.model.censorship.tenantconfiguration.TenantConfigurationCensor;
|
import gr.cite.notification.model.censorship.tenantconfiguration.TenantConfigurationCensor;
|
||||||
import gr.cite.notification.model.persist.tenantconfiguration.TenantConfigurationPersist;
|
import gr.cite.notification.model.persist.tenantconfiguration.TenantConfigurationPersist;
|
||||||
import gr.cite.notification.model.tenantconfiguration.TenantConfiguration;
|
import gr.cite.notification.model.tenantconfiguration.TenantConfiguration;
|
||||||
import gr.cite.notification.model.persist.tenantconfiguration.NotifierListTenantConfigurationPersist;
|
|
||||||
import gr.cite.notification.query.TenantConfigurationQuery;
|
import gr.cite.notification.query.TenantConfigurationQuery;
|
||||||
import gr.cite.notification.query.lookup.NotifierListLookup;
|
import gr.cite.notification.query.lookup.NotifierListLookup;
|
||||||
import gr.cite.notification.query.lookup.TenantConfigurationLookup;
|
import gr.cite.notification.query.lookup.TenantConfigurationLookup;
|
||||||
|
@ -30,7 +29,6 @@ import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -40,11 +38,13 @@ import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.*;
|
import java.util.AbstractMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(path = "api/notification/tenant-configuration")
|
@RequestMapping(path = "api/notification/tenant-configuration")
|
||||||
|
@ -161,4 +161,19 @@ public class TenantConfigurationController {
|
||||||
this.auditService.track(AuditableAction.Tenant_Configuration_Delete, "id", id);
|
this.auditService.track(AuditableAction.Tenant_Configuration_Delete, "id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("notifier-list/available")
|
||||||
|
public NotifierListTenantConfigurationEntity getAvailableNotifiers(@RequestBody NotifierListLookup tenantNotifierListLookup)
|
||||||
|
{
|
||||||
|
logger.debug("querying available notifiers");
|
||||||
|
|
||||||
|
NotifierListTenantConfigurationEntity notifierListData = this.tenantConfigurationService.collectTenantAvailableNotifierList(tenantNotifierListLookup.getNotificationTypes());
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Tenant_Configuration_Notifiers_Query, Map.of(
|
||||||
|
"lookup", tenantNotifierListLookup
|
||||||
|
));
|
||||||
|
//this._auditService.TrackIdentity(AuditableAction.IdentityTracking_Action);
|
||||||
|
|
||||||
|
return notifierListData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class AuditableAction {
|
||||||
public static final EventId TenantConfiguration_LookupByType = new EventId(210004, "TenantConfiguration_LookupByType");
|
public static final EventId TenantConfiguration_LookupByType = new EventId(210004, "TenantConfiguration_LookupByType");
|
||||||
public static final EventId Tenant_Configuration_DefaultUserLocale_Delete = new EventId(21005, "Tenant_Configuration_DefaultUserLocale_Delete");
|
public static final EventId Tenant_Configuration_DefaultUserLocale_Delete = new EventId(21005, "Tenant_Configuration_DefaultUserLocale_Delete");
|
||||||
public static final EventId Tenant_Configuration_DefaultUserLocale_Persist = new EventId(21006, "Tenant_Configuration_DefaultUserLocale_Persist");
|
public static final EventId Tenant_Configuration_DefaultUserLocale_Persist = new EventId(21006, "Tenant_Configuration_DefaultUserLocale_Persist");
|
||||||
|
public static final EventId Tenant_Configuration_Notifiers_Query = new EventId(21007, "Tenant_Configuration_Notifiers_Query");
|
||||||
|
|
||||||
public static final EventId User_Notification_Preference_Query = new EventId(22000, "User_Notification_Preference_Query");
|
public static final EventId User_Notification_Preference_Query = new EventId(22000, "User_Notification_Preference_Query");
|
||||||
public static final EventId User_Notification_Preference_Lookup = new EventId(22001, "User_Notification_Preference_Lookup");
|
public static final EventId User_Notification_Preference_Lookup = new EventId(22001, "User_Notification_Preference_Lookup");
|
||||||
|
|
|
@ -20,6 +20,7 @@ import javax.management.InvalidApplicationException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface TenantConfigurationService {
|
public interface TenantConfigurationService {
|
||||||
|
@ -32,4 +33,6 @@ public interface TenantConfigurationService {
|
||||||
DefaultUserLocaleTenantConfigurationEntity collectTenantUserLocale();
|
DefaultUserLocaleTenantConfigurationEntity collectTenantUserLocale();
|
||||||
|
|
||||||
TenantConfigurationEntity getTenantConfigurationEntityForType(TenantConfigurationType type);
|
TenantConfigurationEntity getTenantConfigurationEntityForType(TenantConfigurationType type);
|
||||||
|
|
||||||
|
NotifierListTenantConfigurationEntity collectTenantAvailableNotifierList(Set<UUID> notificationTypes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.notification.authorization.Permission;
|
import gr.cite.notification.authorization.Permission;
|
||||||
import gr.cite.notification.common.JsonHandlingService;
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
import gr.cite.notification.common.enums.IsActive;
|
import gr.cite.notification.common.enums.IsActive;
|
||||||
|
import gr.cite.notification.common.enums.NotificationContactType;
|
||||||
import gr.cite.notification.common.enums.TenantConfigurationType;
|
import gr.cite.notification.common.enums.TenantConfigurationType;
|
||||||
import gr.cite.notification.common.scope.tenant.TenantScope;
|
import gr.cite.notification.common.scope.tenant.TenantScope;
|
||||||
import gr.cite.notification.common.types.tenantconfiguration.DefaultUserLocaleTenantConfigurationEntity;
|
import gr.cite.notification.common.types.tenantconfiguration.DefaultUserLocaleTenantConfigurationEntity;
|
||||||
|
@ -51,7 +52,10 @@ import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class TenantConfigurationServiceImpl implements TenantConfigurationService {
|
public class TenantConfigurationServiceImpl implements TenantConfigurationService {
|
||||||
|
@ -77,6 +81,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
|
||||||
private final QueryFactory queryFactory;
|
private final QueryFactory queryFactory;
|
||||||
private final EventBroker eventBroker;
|
private final EventBroker eventBroker;
|
||||||
private final TenantScope tenantScope;
|
private final TenantScope tenantScope;
|
||||||
|
private final Map<UUID, List<NotificationContactType>> globalPoliciesMap;
|
||||||
@Autowired
|
@Autowired
|
||||||
public TenantConfigurationServiceImpl(
|
public TenantConfigurationServiceImpl(
|
||||||
TenantEntityManager entityManager,
|
TenantEntityManager entityManager,
|
||||||
|
@ -85,7 +90,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
|
||||||
BuilderFactory builderFactory,
|
BuilderFactory builderFactory,
|
||||||
ConventionService conventionService,
|
ConventionService conventionService,
|
||||||
ErrorThesaurusProperties errors,
|
ErrorThesaurusProperties errors,
|
||||||
MessageSource messageSource, JsonHandlingService jsonHandlingService, QueryFactory queryFactory, EventBroker eventBroker, TenantScope tenantScope) {
|
MessageSource messageSource, JsonHandlingService jsonHandlingService, QueryFactory queryFactory, EventBroker eventBroker, TenantScope tenantScope, Map<UUID, List<NotificationContactType>> globalPoliciesMap) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
@ -97,6 +102,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
|
||||||
this.queryFactory = queryFactory;
|
this.queryFactory = queryFactory;
|
||||||
this.eventBroker = eventBroker;
|
this.eventBroker = eventBroker;
|
||||||
this.tenantScope = tenantScope;
|
this.tenantScope = tenantScope;
|
||||||
|
this.globalPoliciesMap = globalPoliciesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
public TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||||
|
@ -214,4 +220,19 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
|
||||||
return query.first();
|
return query.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NotifierListTenantConfigurationEntity collectTenantAvailableNotifierList(Set<UUID> notificationTypes) {
|
||||||
|
this.authorizationService.authorizeForce(Permission.BrowseTenantConfiguration);
|
||||||
|
Map<UUID, List<NotificationContactType>> currentNotificationListPolicies = this.globalPoliciesMap;
|
||||||
|
|
||||||
|
if (notificationTypes != null && !notificationTypes.isEmpty())
|
||||||
|
{
|
||||||
|
return new NotifierListTenantConfigurationEntity(currentNotificationListPolicies
|
||||||
|
.entrySet().stream()
|
||||||
|
.filter(x -> notificationTypes.contains(x.getKey()))
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||||
|
}
|
||||||
|
else return new NotifierListTenantConfigurationEntity(currentNotificationListPolicies);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import gr.cite.notification.authorization.OwnedResource;
|
||||||
import gr.cite.notification.authorization.Permission;
|
import gr.cite.notification.authorization.Permission;
|
||||||
import gr.cite.notification.common.enums.IsActive;
|
import gr.cite.notification.common.enums.IsActive;
|
||||||
import gr.cite.notification.common.enums.NotificationContactType;
|
import gr.cite.notification.common.enums.NotificationContactType;
|
||||||
|
import gr.cite.notification.common.scope.tenant.TenantScope;
|
||||||
import gr.cite.notification.common.types.tenantconfiguration.NotifierListTenantConfigurationEntity;
|
import gr.cite.notification.common.types.tenantconfiguration.NotifierListTenantConfigurationEntity;
|
||||||
import gr.cite.notification.config.notification.NotificationConfig;
|
import gr.cite.notification.config.notification.NotificationConfig;
|
||||||
import gr.cite.notification.data.TenantEntityManager;
|
import gr.cite.notification.data.TenantEntityManager;
|
||||||
|
@ -46,6 +47,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
|
||||||
private final Map<UUID, List<NotificationContactType>> globalPoliciesMap;
|
private final Map<UUID, List<NotificationContactType>> globalPoliciesMap;
|
||||||
private final ErrorThesaurusProperties errors;
|
private final ErrorThesaurusProperties errors;
|
||||||
private final TenantEntityManager entityManager;
|
private final TenantEntityManager entityManager;
|
||||||
|
private final TenantScope tenantScope;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UserNotificationPreferenceServiceImpl(QueryFactory queryFactory,
|
public UserNotificationPreferenceServiceImpl(QueryFactory queryFactory,
|
||||||
|
@ -54,7 +56,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
|
||||||
TenantConfigurationService tenantConfigurationService,
|
TenantConfigurationService tenantConfigurationService,
|
||||||
@Qualifier(NotificationConfig.BeanQualifier.GLOBAL_POLICIES_MAP)
|
@Qualifier(NotificationConfig.BeanQualifier.GLOBAL_POLICIES_MAP)
|
||||||
Map<UUID, List<NotificationContactType>> globalPoliciesMap,
|
Map<UUID, List<NotificationContactType>> globalPoliciesMap,
|
||||||
ErrorThesaurusProperties errors, TenantEntityManager entityManager) {
|
ErrorThesaurusProperties errors, TenantEntityManager entityManager, TenantScope tenantScope) {
|
||||||
this.queryFactory = queryFactory;
|
this.queryFactory = queryFactory;
|
||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
this.authService = authService;
|
this.authService = authService;
|
||||||
|
@ -62,6 +64,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
|
||||||
this.globalPoliciesMap = globalPoliciesMap;
|
this.globalPoliciesMap = globalPoliciesMap;
|
||||||
this.errors = errors;
|
this.errors = errors;
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
this.tenantScope = tenantScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,7 +132,14 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
|
||||||
.build(new BaseFieldSet(UserNotificationPreference._userId, UserNotificationPreference._type,
|
.build(new BaseFieldSet(UserNotificationPreference._userId, UserNotificationPreference._type,
|
||||||
UserNotificationPreference._channel, UserNotificationPreference._ordinal), this.queryFactory
|
UserNotificationPreference._channel, UserNotificationPreference._ordinal), this.queryFactory
|
||||||
.query(UserNotificationPreferenceQuery.class)
|
.query(UserNotificationPreferenceQuery.class)
|
||||||
.userId(ids).collect()).stream().collect(Collectors.groupingBy(UserNotificationPreference::getUserId)); //GK: Yep that exist on JAVA Streams
|
.userId(ids).collect()).stream().filter(x -> {
|
||||||
|
try {
|
||||||
|
return !this.tenantScope.isMultitenant() || this.tenantScope.isDefaultTenant() ? x.getTenantId() == null : x.getTenantId() == this.tenantScope.getTenant();
|
||||||
|
} catch (InvalidApplicationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(Collectors.groupingBy(UserNotificationPreference::getUserId)); //GK: Yep that exist on JAVA Streams
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<UUID, List<NotificationContactType>> mergeNotifierPolicies(Map<UUID, List<NotificationContactType>> overrides, Map<UUID, List<NotificationContactType>> bases)
|
private Map<UUID, List<NotificationContactType>> mergeNotifierPolicies(Map<UUID, List<NotificationContactType>> overrides, Map<UUID, List<NotificationContactType>> bases)
|
||||||
|
@ -177,7 +187,13 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
|
||||||
|
|
||||||
List<UserNotificationPreferenceEntity> updatedPreferences = new ArrayList<>();
|
List<UserNotificationPreferenceEntity> updatedPreferences = new ArrayList<>();
|
||||||
for (NotificationContactType contactType : contactTypes) {
|
for (NotificationContactType contactType : contactTypes) {
|
||||||
UserNotificationPreferenceEntity preference = preferences.stream().filter(x -> x.getChannel() == contactType).findFirst().orElse(null);
|
UserNotificationPreferenceEntity preference = preferences.stream().filter(x -> {
|
||||||
|
try {
|
||||||
|
return x.getChannel() == contactType && (!this.tenantScope.isMultitenant() ||this.tenantScope.isDefaultTenant() ? x.getTenantId() == null : x.getTenantId() == this.tenantScope.getTenant());
|
||||||
|
} catch (InvalidApplicationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).findFirst().orElse(null);
|
||||||
|
|
||||||
boolean isUpdate = preference != null;
|
boolean isUpdate = preference != null;
|
||||||
if (preference != null) {
|
if (preference != null) {
|
||||||
|
|
Loading…
Reference in New Issue