aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-web/archiva-webapp
diff options
context:
space:
mode:
authorMartin Stockhammer <martin_s@apache.org>2020-12-24 10:37:55 +0100
committerMartin Stockhammer <martin_s@apache.org>2020-12-24 10:37:55 +0100
commitcb0e4d19d78956b536c62772ae042c281d07ad9f (patch)
tree460f837cdd12d6ece1dac0d1beabbf1770582434 /archiva-modules/archiva-web/archiva-webapp
parent7744b086d7f71b67f436c0f617d262b2ae91c8f6 (diff)
downloadarchiva-cb0e4d19d78956b536c62772ae042c281d07ad9f.tar.gz
archiva-cb0e4d19d78956b536c62772ae042c281d07ad9f.zip
Improving error handling
Diffstat (limited to 'archiva-modules/archiva-web/archiva-webapp')
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/app-notification.ts3
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/roles/manage-roles-edit/manage-roles-edit.component.ts35
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html3
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts8
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.ts27
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/toast/toast.component.ts2
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/with-loading.pipe.ts8
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts50
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/toast.service.ts42
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json12
10 files changed, 127 insertions, 63 deletions
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/app-notification.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/app-notification.ts
index 787762b0a..ae1b0a45a 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/app-notification.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/app-notification.ts
@@ -33,7 +33,6 @@ export class AppNotification {
this.header = header;
this.body = body;
this.timestamp = timestamp;
- console.log("Options " + JSON.stringify(options));
if (options.classname) {
this.classname = options.classname;
}
@@ -49,7 +48,7 @@ export class AppNotification {
}
public toString(): string {
- return this.origin + ',classname:' + this.classname + ", delay:" + this.delay +", context: "+JSON.stringify(this.contextData);
+ return this.origin + ',classname:' + this.classname + ", delay:" + this.delay ;
}
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/roles/manage-roles-edit/manage-roles-edit.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/roles/manage-roles-edit/manage-roles-edit.component.ts
index 321557b85..7654ee929 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/roles/manage-roles-edit/manage-roles-edit.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/roles/manage-roles-edit/manage-roles-edit.component.ts
@@ -16,16 +16,7 @@
* under the License.
*/
-import {
- AfterContentInit,
- ChangeDetectorRef,
- Component,
- EventEmitter,
- OnInit,
- Output,
- TemplateRef,
- ViewChild
-} from '@angular/core';
+import {AfterContentInit, Component, EventEmitter, OnInit, Output, ViewChild} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
import {FormBuilder, Validators} from "@angular/forms";
import {RoleService} from "@app/services/role.service";
@@ -42,6 +33,7 @@ import {UserService} from "@app/services/user.service";
import {UserInfo} from '@app/model/user-info';
import {HttpResponse} from "@angular/common/http";
import {PaginatedEntitiesComponent} from "@app/modules/shared/paginated-entities/paginated-entities.component";
+import {ToastService} from "@app/services/toast.service";
@Component({
selector: 'app-manage-roles-edit',
@@ -73,7 +65,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
roleIdEvent: EventEmitter<string> = new EventEmitter<string>(true);
constructor(private route: ActivatedRoute, public roleService: RoleService, private userService: UserService,
- public fb: FormBuilder, private changeDetect : ChangeDetectorRef) {
+ public fb: FormBuilder, private toastService: ToastService) {
super(fb);
super.init(fb.group({
id: [''],
@@ -151,7 +143,9 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
} else {
return this.roleService.getRole(myId).pipe(tap(role => {
this.roleCache.set(role.id, role);
- }),catchError(() => of(this.createRole(id))));
+ }),catchError((error : ErrorResult) => {
+ this.showError(error, "roles.edit.errors.retrieveFailed")
+ return of(this.createRole(id)); }));
}
}));
}
@@ -192,6 +186,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.error = true;
this.success = false;
this.errorResult = err;
+ this.showError(err, 'roles.edit.errors.updateFailed',{'role_id':role.id})
return [];
})
).subscribe(roleInfo => {
@@ -199,6 +194,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.success = true;
this.errorResult = null;
this.result = roleInfo;
+ this.showSuccess('roles.edit.success.updated',{'role_id':role.id})
this.editMode = false;
});
@@ -233,6 +229,17 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
return item.user_id;
}
+ showError(err: ErrorResult, errorKey:string, params:any={}) : void {
+ let message = err.error_messages.length>0?err.error_messages[0]:''
+ params['message']=message
+ this.toastService.showErrorByKey('manage-roles-edit',errorKey,params)
+ }
+
+ showSuccess(successKey:string, params:any={}) : void {
+ console.log("Success " + successKey + " - " + JSON.stringify(params));
+ this.toastService.showSuccessByKey('manage-roles-edit',successKey,params)
+ }
+
assignUserRole() {
let userId;
if (typeof(this.userSearchModel)=='string') {
@@ -248,6 +255,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.error = true;
this.success = false;
this.errorResult = err;
+ this.showError(err, 'roles.edit.errors.assignFailed', {'role_id':this.editRole.id,'user_id':userId})
return [];
})
).subscribe((response : HttpResponse<Role>) => {
@@ -256,6 +264,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.errorResult = null;
this.result = response.body;
this.roleUserComponent.changePage(1);
+ this.showSuccess('roles.edit.success.assign',{'role_id':this.editRole.id,'user_id':userId})
this.userSearchModel=''
});
}
@@ -269,6 +278,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.error = true;
this.success = false;
this.errorResult = err;
+ this.showError(err, 'roles.edit.errors.unassignFailed',{'role_id':this.editRole.id,'user_id':user_id})
return [];
})
).subscribe((response : HttpResponse<Role>) => {
@@ -278,6 +288,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.errorResult = null;
this.result = response.body;
this.roleUserComponent.changePage(1);
+ this.showSuccess('roles.edit.success.unassign',{'role_id':this.editRole.id,'user_id':user_id})
}
);
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html
index 915c81261..c04ee50c6 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-add/manage-users-add.component.html
@@ -90,9 +90,6 @@
<button class="btn btn-primary" type="submit"
[attr.disabled]="userForm.valid?null:true">{{'users.add.submit'|translate}}</button>
</div>
- <div class="form-group col-md-8">
- <button class="btn btn-primary" (click)="showMessage()">Show Message</button>
- </div>
<ng-template #successTmpl let-userId="user_id">
User <a [routerLink]="['/security','users','edit',userId]">{{userId}}</a> was added to the list.
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts
index 1beb1f0e0..9608bba0b 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts
@@ -17,16 +17,16 @@
*/
import {AfterViewInit, Component, EventEmitter, OnInit, Output} from '@angular/core';
-import { Role } from '@app/model/role';
+import {Role} from '@app/model/role';
import {UserService} from "@app/services/user.service";
import {ActivatedRoute} from "@angular/router";
-import {catchError, filter, map, multicast, share, switchMap, tap} from "rxjs/operators";
+import {catchError, filter, map, share, switchMap, tap} from "rxjs/operators";
import {RoleTree} from "@app/model/role-tree";
import {RoleService} from "@app/services/role.service";
import {RoleTemplate} from "@app/model/role-template";
-import {Observable, of} from "rxjs";
+import {Observable} from "rxjs";
import {Util} from "@app/modules/shared/shared.module";
-import { RoleResult } from './role-result';
+import {RoleResult} from './role-result';
import {fromArray} from "rxjs/internal/observable/fromArray";
import {ErrorResult} from "@app/model/error-result";
import {HttpResponse} from "@angular/common/http";
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.ts
index 8e2e16650..f7d2188a8 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.ts
@@ -16,26 +16,13 @@
* under the License.
*/
-import {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
-import {concat, merge, Observable, of, pipe, Subject} from "rxjs";
-import {
- concatAll,
- debounceTime,
- delay,
- distinctUntilChanged,
- filter,
- map,
- mergeMap,
- pluck,
- share,
- startWith,
- switchMap,
- tap
-} from "rxjs/operators";
-import {EntityService} from "../../../model/entity-service";
-import {FieldToggle} from "../../../model/field-toggle";
-import {PageQuery} from "@app/modules/shared/model/page-query";
-import { LoadingValue } from '../shared.module';
+import {AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {concat, merge, Observable, of, Subject} from "rxjs";
+import {debounceTime, distinctUntilChanged, filter, map, pluck, startWith, switchMap} from "rxjs/operators";
+import {EntityService} from "@app/model/entity-service";
+import {FieldToggle} from "@app/model/field-toggle";
+import {PageQuery} from "../model/page-query";
+import {LoadingValue} from '../model/loading-value';
import {PagedResult} from "@app/model/paged-result";
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/toast/toast.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/toast/toast.component.ts
index 0813f6c7b..ff6a03313 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/toast/toast.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/toast/toast.component.ts
@@ -41,7 +41,7 @@ import {AppNotification} from "@app/model/app-notification";
<ng-template #text>{{ toast.body }}</ng-template>
</ngb-toast>
`,
- styles: [".ngb-toasts{margin:.5em;padding:0.5em;position:fixed;right:2px;top:2px;z-index:1200}"
+ styles: [".ngb-toasts{margin:.5em;padding:0.5em;position:fixed;right:2px;top:20px;z-index:1200}"
],
host: {'[class.ngb-toasts]': 'true'}
})
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/with-loading.pipe.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/with-loading.pipe.ts
index 8de45eda5..dbb9cd04b 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/with-loading.pipe.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/with-loading.pipe.ts
@@ -16,10 +16,10 @@
* under the License.
*/
-import { Pipe, PipeTransform } from '@angular/core';
-import {concat, isObservable, of } from 'rxjs';
-import {catchError, map, startWith, tap } from 'rxjs/operators';
-import {LoadingValue} from "@app/modules/shared/shared.module";
+import {Pipe, PipeTransform} from '@angular/core';
+import {isObservable, of} from 'rxjs';
+import {catchError, map, startWith} from 'rxjs/operators';
+import {LoadingValue} from "@app/modules/shared/model/loading-value";
@Pipe({
name: 'withLoading'
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts
index e5b7e3954..5886c8ae7 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/role.service.ts
@@ -19,13 +19,14 @@
import { Injectable } from '@angular/core';
import {ArchivaRequestService} from "@app/services/archiva-request.service";
import {RoleTemplate} from "@app/model/role-template";
-import { Observable } from 'rxjs';
+import {Observable, throwError} from 'rxjs';
import { Role } from '@app/model/role';
-import {HttpResponse} from "@angular/common/http";
+import {HttpErrorResponse, HttpResponse} from "@angular/common/http";
import {PagedResult} from "@app/model/paged-result";
import {UserInfo} from "@app/model/user-info";
import {RoleUpdate} from "@app/model/role-update";
import { User } from '@app/model/user';
+import {catchError} from "rxjs/operators";
@Injectable({
providedIn: 'root'
@@ -35,15 +36,24 @@ export class RoleService {
constructor(private rest: ArchivaRequestService) { }
public getTemplates() : Observable<RoleTemplate[]> {
- return this.rest.executeRestCall("get", "redback", "roles/templates", null);
+ return this.rest.executeRestCall<RoleTemplate[]>("get", "redback", "roles/templates", null).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public assignRole(roleId, userId) : Observable<HttpResponse<Role>> {
- return this.rest.executeResponseCall<Role>("put", "redback", "roles/" + roleId + "/user/" + userId, null);
+ return this.rest.executeResponseCall<Role>("put", "redback", "roles/" + roleId + "/user/" + userId, null).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public unAssignRole(roleId, userId) : Observable<HttpResponse<Role>> {
- return this.rest.executeResponseCall<Role>("delete", "redback", "roles/" + roleId + "/user/" + userId, null);
+ return this.rest.executeResponseCall<Role>("delete", "redback", "roles/" + roleId + "/user/" + userId, null).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public query(searchTerm: string, offset: number = 0, limit: number = 10, orderBy: string[] = ['id'], order: string = 'asc'): Observable<PagedResult<Role>> {
@@ -59,7 +69,10 @@ export class RoleService {
'limit': limit,
'orderBy': orderBy,
'order': order
- });
+ }).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public queryAssignedUsers(roleId: string,
@@ -77,7 +90,10 @@ export class RoleService {
'limit': limit,
'orderBy': orderBy,
'order': order
- });
+ }).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
/**
@@ -108,7 +124,10 @@ export class RoleService {
'limit': limit,
'orderBy': orderBy,
'order': order
- });
+ }).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public queryUnAssignedUsers(roleId: string,
@@ -126,16 +145,25 @@ export class RoleService {
'limit': limit,
'orderBy': orderBy,
'order': order
- });
+ }).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public getRole(roleId:string) : Observable<Role> {
- return this.rest.executeRestCall("get", "redback", "roles/" + roleId, null);
+ return this.rest.executeRestCall<Role>("get", "redback", "roles/" + roleId, null).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
public updateRole(role:RoleUpdate) : Observable<Role> {
- return this.rest.executeRestCall("patch", "redback", "roles/" + role.id, role);
+ return this.rest.executeRestCall<Role>("patch", "redback", "roles/" + role.id, role).pipe(
+ catchError((error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }));
}
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/toast.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/toast.service.ts
index b168a0f51..1b1a934aa 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/toast.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/toast.service.ts
@@ -19,6 +19,7 @@
import { Injectable, TemplateRef } from '@angular/core';
import {AppNotification} from "@app/model/app-notification";
import {not} from "rxjs/internal-compatibility";
+import {TranslateService} from "@ngx-translate/core";
@Injectable({
providedIn: 'root'
@@ -30,9 +31,9 @@ export class ToastService {
toasts:AppNotification[]=[]
toastHistory:AppNotification[]=[]
- constructor() { }
+ constructor(private translator: TranslateService) { }
- show(origin:string, textOrTpl: string | TemplateRef<any>, options: any = {}) {
+ public show(origin:string, textOrTpl: string | TemplateRef<any>, options: any = {}): void {
let notification = new AppNotification(origin, textOrTpl, "", options);
this.toasts.push(notification);
this.toastHistory.push(notification);
@@ -45,7 +46,7 @@ export class ToastService {
console.log("Notification " + notification);
}
- showStandard(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) {
+ public showStandard(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) : void {
options.classname='bg-primary'
if (!options.delay) {
options.delay=8000
@@ -53,7 +54,17 @@ export class ToastService {
this.show(origin,textOrTpl,options)
}
- showError(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) {
+ public showStandardByKey(origin:string,translationKey:string, params:any={}, options:any={} ) : void {
+ let message:string;
+ if (params) {
+ message = this.translator.instant(translationKey, params);
+ } else {
+ message = this.translator.instant(translationKey);
+ }
+ this.showStandard(origin, message, options);
+ }
+
+ public showError(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) : void {
options.classname='bg-warning'
options.type='error'
if (!options.delay) {
@@ -62,7 +73,17 @@ export class ToastService {
this.show(origin,textOrTpl,options)
}
- showSuccess(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) {
+ public showErrorByKey(origin:string,translationKey:string, params:any={}, options:any={} ) : void {
+ let message:string;
+ if (params) {
+ message = this.translator.instant(translationKey, params);
+ } else {
+ message = this.translator.instant(translationKey);
+ }
+ this.showError(origin, message, options);
+ }
+
+ public showSuccess(origin:string,textOrTpl:string|TemplateRef<any>, options:any={}) : void {
options.classname='bg-info'
options.type='success'
if (!options.delay) {
@@ -71,6 +92,17 @@ export class ToastService {
this.show(origin,textOrTpl,options)
}
+ public showSuccessByKey(origin:string,translationKey:string, params:any={}, options:any={} ) : void {
+ let message:string;
+ if (params) {
+ message = this.translator.instant(translationKey, params);
+ } else {
+ message = this.translator.instant(translationKey);
+ }
+ this.showSuccess(origin, message, options);
+ }
+
+
remove(toast) {
this.toasts = this.toasts.filter(t => t != toast);
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
index 0be67d397..e39cf2157 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json
@@ -143,7 +143,17 @@
"noUsersAssigned": "There are no users assigned to this role",
"assignUserSearch": "Search and assign users to this role",
"userSearchFailed": "Sorry, could not load users",
- "assignButton": "Assign"
+ "assignButton": "Assign",
+ "errors": {
+ "updateFailed": "Could not update role {role_id}: {message}",
+ "assignFailed": "Could not assign role {role_id} to user {user_id}: {message}",
+ "retrieveFailed": "Could not retrieve role information: {message}"
+ },
+ "success": {
+ "updated": "Role {role_id} was updated",
+ "assign": "Role {role_id} was assigned to user {user_id}",
+ "unassign": "Removed assignment of {role_id} to {user_id}"
+ }
},
"attributes": {
"id": "Identifier",