aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules
diff options
context:
space:
mode:
authorMartin Stockhammer <martin_s@apache.org>2020-11-11 21:01:46 +0100
committerMartin Stockhammer <martin_s@apache.org>2020-11-11 21:01:46 +0100
commit055964cce1d8c3b272227520836cd494048ab3e4 (patch)
tree6f1f3e13837c929fa13ec160628a6ba490c6411d /archiva-modules
parent1caa397790ee006b645e6ca9f666382ff0a2f97f (diff)
downloadarchiva-055964cce1d8c3b272227520836cd494048ab3e4.tar.gz
archiva-055964cce1d8c3b272227520836cd494048ab3e4.zip
Updating user add component
Diffstat (limited to 'archiva-modules')
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/error-result.ts1
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.spec.ts25
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.ts24
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/manage-users/manage-users.component.html3
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html94
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts81
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html2
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts53
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts13
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json18
10 files changed, 258 insertions, 56 deletions
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/error-result.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/error-result.ts
index 64e97659f..b54fa848f 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/error-result.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/error-result.ts
@@ -20,6 +20,7 @@ import {ErrorMessage} from "./error-message";
export class ErrorResult {
error_messages: Array<ErrorMessage>
+ status: number;
constructor(errorMessages: Array<ErrorMessage>) {
this.error_messages = errorMessages;
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.spec.ts
new file mode 100644
index 000000000..40e143798
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.spec.ts
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { User } from './user';
+
+describe('User', () => {
+ it('should create an instance', () => {
+ expect(new User()).toBeTruthy();
+ });
+});
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.ts
new file mode 100644
index 000000000..f264d0218
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/user.ts
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { UserInfo } from './user-info';
+
+export class User extends UserInfo {
+ password: string;
+ confirm_password: string;
+}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/manage-users/manage-users.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/manage-users/manage-users.component.html
index c61718009..08b3fca81 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/manage-users/manage-users.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/manage-users/manage-users.component.html
@@ -24,6 +24,9 @@
<li class="nav-item">
<a class="nav-link" routerLink="/user/users/add" routerLinkActive="active" href="#">{{'users.add.head' |translate }}</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" routerLink="/user/users/edit/guest" routerLinkActive="active" href="#">{{'users.edit.head' |translate }}</a>
+ </li>
</ul>
<router-outlet ></router-outlet> \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
index 1bfac6606..ad538a838 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.html
@@ -18,47 +18,67 @@
-->
<form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()">
- <fieldset>
- <div class="form-group col-md-8">
- <label for="userId">{{'users.attributes.user_id' |translate}}</label>
- <input type="text" class="form-control" formControlName="userId" id="userId"
- [ngClass]="valid('userId')"
- placeholder="{{'users.input.user_id'|translate}}">
- <small>{{'users.input.small.user_id'|translate}}</small>
+ <div class="form-group col-md-8">
+ <label for="user_id">{{'users.attributes.user_id' |translate}}</label>
+ <input type="text" class="form-control" formControlName="user_id" id="user_id"
+ [ngClass]="valid('user_id')"
+ placeholder="{{'users.input.user_id'|translate}}">
+ <small>{{'users.input.small.user_id'|translate:{'minSize':this.minUserIdSize} }}</small>
+ </div>
+ <div class="form-group col-md-8">
+ <label for="full_name">{{'users.attributes.full_name' |translate}}</label>
+ <input type="text" class="form-control" formControlName="full_name" id="full_name"
+ [ngClass]="valid('full_name')"
+ placeholder="{{'users.input.full_name'|translate}}">
+ <small>{{'users.input.small.full_name'|translate}}</small>
+ </div>
+ <div class="form-group col-md-8">
+ <label for="email">{{'users.attributes.email' |translate}}</label>
+ <input type="text" class="form-control" formControlName="email" id="email"
+ [ngClass]="valid('email')"
+ placeholder="{{'users.input.email'|translate}}">
+ </div>
+ <div class="form-group col-md-8">
+ <label for="password">{{'users.attributes.password' |translate}}</label>
+ <input type="password" class="form-control" formControlName="password" id="password"
+ [ngClass]="valid('password')"
+ placeholder="{{'users.input.password'|translate}}">
+ </div>
+ <div class="form-group col-md-8">
+ <label for="confirm_password">{{'users.attributes.confirm_password' |translate}}</label>
+ <input type="password" class="form-control" formControlName="confirm_password" id="confirm_password"
+ [ngClass]="valid('confirm_password')"
+ placeholder="{{'users.input.confirm_password'|translate}}">
+ </div>
+ <div class="form-group col-md-8">
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" value="" formControlName="locked" id="locked">
+ <label class="form-check-label" for="locked">
+ {{'users.attributes.locked'|translate}}
+ </label>
</div>
- <div class="form-group col-md-8">
- <label for="fullName">{{'users.attributes.full_name' |translate}}</label>
- <input type="text" class="form-control" formControlName="fullName" id="fullName"
- [ngClass]="valid('fullName')"
- placeholder="{{'users.input.full_name'|translate}}">
- <small>{{'users.input.small.full_name'|translate}}</small>
+ <div class="form-check">
+ <input class="form-check-input" type="checkbox" value="" formControlName="password_change_required"
+ id="password_change_required" checked>
+ <label class="form-check-label" for="password_change_required">
+ {{'users.attributes.password_change_required'|translate}}
+ </label>
</div>
- <div class="form-group col-md-8">
- <label for="email">{{'users.attributes.email' |translate}}</label>
- <input type="text" class="form-control" formControlName="email" id="email"
- [ngClass]="valid('email')"
- placeholder="{{'users.input.email'|translate}}">
- </div>
- <div class="form-group col-md-8">
- <div class="form-check">
- <input class="form-check-input" type="checkbox" value="" formControlName="locked" id="locked">
- <label class="form-check-label" for="locked">
- {{'users.attributes.locked'|translate}}
- </label>
- </div>
- <div class="form-check">
- <input class="form-check-input" type="checkbox" value="" formControlName="passwordChangeRequired"
- id="password_change_required" checked>
- <label class="form-check-label" for="password_change_required">
- {{'users.attributes.password_change_required'|translate}}
- </label>
- </div>
- </div>
- <div class="form-group col-md-8">
+ </div>
+ <div class="form-group col-md-8">
<button class="btn btn-primary" type="submit"
[disabled]="!userForm.valid">{{'users.add.submit'|translate}}</button>
- </div>
- </fieldset>
+ </div>
+ <div *ngIf="success" class="alert alert-success" role="alert">
+ User <a [routerLink]="['user','users','edit',userid]">{{userid}}</a> was added to the list.
+ </div>
+ <div *ngIf="error" class="alert alert-danger" role="alert" >
+ <h4 class="alert-heading">Errors</h4>
+ <ng-container *ngFor="let message of errorResult?.error_messages; first as isFirst" >
+ <hr *ngIf="!isFirst">
+ <p>{{message.message}}</p>
+ </ng-container>
+ </div>
</form>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
index ce95bff62..6a50028b7 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-add/manage-users-add.component.ts
@@ -18,8 +18,14 @@
*/
import {Component, OnInit} from '@angular/core';
-import {FormControl, FormGroup, Validators, FormBuilder} from '@angular/forms';
+import {Validators, FormBuilder, FormGroup} from '@angular/forms';
import {UserService} from "../../../../services/user.service";
+import {User} from "../../../../model/user";
+import { UserInfo } from 'src/app/model/user-info';
+import {HttpErrorResponse} from "@angular/common/http";
+import {ErrorResult} from "../../../../model/error-result";
+import {catchError} from "rxjs/operators";
+import {of, throwError} from 'rxjs';
@Component({
selector: 'app-manage-users-add',
@@ -28,12 +34,23 @@ import {UserService} from "../../../../services/user.service";
})
export class ManageUsersAddComponent implements OnInit {
+ minUserIdSize=8;
+ success:boolean=false;
+ error:boolean=false;
+ errorResult:ErrorResult;
+ result:string;
+ userid:string;
+
userForm = this.fb.group({
- userId: ['', [Validators.required, Validators.minLength(8)]],
- fullName: ['', Validators.required],
+ user_id: ['', [Validators.required, Validators.minLength(this.minUserIdSize)]],
+ full_name: ['', Validators.required],
email: ['', [Validators.required,Validators.email]],
locked: [false],
- passwordChangeRequired: [true]
+ password_change_required: [true],
+ password: [''],
+ confirm_password: [''],
+ }, {
+ validator: MustMatch('password', 'confirm_password')
})
constructor(private userService: UserService, private fb: FormBuilder) {
@@ -45,13 +62,41 @@ export class ManageUsersAddComponent implements OnInit {
onSubmit() {
// Process checkout data here
- console.warn('Your order has been submitted', JSON.stringify(this.userForm.value));
+ this.result=null;
+ if (this.userForm.valid) {
+ let user = this.copyForm(['user_id','full_name','email','locked','password_change_required',
+ 'password','confirm_password'])
+ console.info('Adding user ' + user);
+ this.userService.addUser(user).pipe(catchError((error : ErrorResult)=> {
+ console.log("Error " + error + " - " + typeof (error) + " - " + JSON.stringify(error));
+ if (error.status==422) {
+ console.warn("Validation error");
+
+ }
+ this.errorResult = error;
+ this.success=false;
+ this.error=true;
+ return throwError(error);
+ })).subscribe((location : string ) => {
+ this.result = location;
+ this.success=true;
+ this.error = false;
+ this.userid = location.substring(location.lastIndexOf('/') + 1);
+ });
+ }
}
- get userId() {
- return this.userForm.get('userId');
+
+ private copyForm(properties:string[]) : User {
+ let user : any = new User();
+ for (let prop of properties) {
+ user[prop] = this.userForm.get(prop).value;
+ }
+ console.log("User " + user);
+ return user;
}
+
valid(field:string) : string {
let formField = this.userForm.get(field);
if (formField.dirty||formField.touched) {
@@ -65,4 +110,26 @@ export class ManageUsersAddComponent implements OnInit {
}
}
+
+
+
}
+
+export function MustMatch(controlName: string, matchingControlName: string) {
+ return (formGroup: FormGroup) => {
+ const control = formGroup.controls[controlName];
+ const matchingControl = formGroup.controls[matchingControlName];
+
+ if (matchingControl.errors && !matchingControl.errors.mustMatch) {
+ // return if another validator has already found an error on the matchingControl
+ return;
+ }
+
+ // set error on matchingControl if validation fails
+ if (control.value !== matchingControl.value) {
+ matchingControl.setErrors({ mustMatch: true });
+ } else {
+ matchingControl.setErrors(null);
+ }
+ }
+} \ No newline at end of file
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
index fbd689508..960e16d3a 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
@@ -50,7 +50,7 @@
[ngClass]="user.validated?'fa-check-circle':'fa-circle'"></span></td>
<td><span class="far" [attr.aria-valuetext]="user.locked"
[ngClass]="user.locked?'fa-check-circle':'fa-circle'"></span></td>
- <td><span class="far" [attr.aria-valuetext]="user.passwordChangeRequired"
+ <td><span class="far" [attr.aria-valuetext]="user.password_change_required"
[ngClass]="user.password_change_required?'fa-check-circle':'fa-circle'"></span></td>
<td>{{user.timestamp_last_login | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
<td>{{user.timestamp_account_creation | date : 'yyyy-MM-ddTHH:mm:ss'}}</td>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
index 0227893c1..2f1e9939f 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/archiva-request.service.ts
@@ -17,11 +17,12 @@
* under the License.
*/
import {Injectable} from '@angular/core';
-import {HttpClient} from "@angular/common/http";
+import {HttpClient, HttpErrorResponse, HttpResponse} from "@angular/common/http";
import {environment} from "../../environments/environment";
import {Observable} from "rxjs";
import {ErrorMessage} from "../model/error-message";
import {TranslateService} from "@ngx-translate/core";
+import {ErrorResult} from "../model/error-result";
@Injectable({
providedIn: 'root'
@@ -42,6 +43,21 @@ export class ArchivaRequestService {
* @param input the input data, if this is a POST or UPDATE request
*/
executeRestCall<R>(type: string, module: string, service: string, input: object): Observable<R> {
+ let httpArgs = this.getHttpOptions(type, module, service, input);
+ httpArgs['options']['observe'] = 'body';
+ httpArgs['options']['responseType'] = 'json';
+
+ let lType = type.toLowerCase();
+ if (lType == "get") {
+ return this.http.get<R>(httpArgs.url, httpArgs.options);
+ } else if (lType == "head" ) {
+ return this.http.head<R>(httpArgs.url, httpArgs.options);
+ } else if (lType == "post") {
+ return this.http.post<R>(httpArgs.url, input, httpArgs.options);
+ }
+ }
+
+ private getHttpOptions(type: string, module: string, service: string, input: object) {
let modulePath = environment.application.servicePaths[module];
let url = environment.application.baseUrl + environment.application.restPath + "/" + modulePath + "/" + service;
let token = this.getToken();
@@ -53,14 +69,28 @@ export class ArchivaRequestService {
} else {
headers = {};
}
- if (type == "get") {
+ let options = {'headers': headers}
+ if (type.toLowerCase()=='get') {
let params = {}
if (input!=null) {
params = input;
}
- return this.http.get<R>(url, {"headers": headers,"params":params});
- } else if (type == "post") {
- return this.http.post<R>(url, input, {"headers": headers});
+ options['params'] = params;
+ }
+ return {'url':url, 'options':options}
+ }
+
+ executeResponseCall<R>(type: string, module: string, service:string, input:object) : Observable<HttpResponse<R>> {
+ let httpArgs = this.getHttpOptions(type, module, service, input);
+ httpArgs['options']['observe'] = 'response';
+ httpArgs['options']['responseType'] = 'json';
+ let lType = type.toLowerCase();
+ if (lType == "get") {
+ return this.http.get<HttpResponse<R>>(httpArgs.url, httpArgs.options);
+ } else if (lType=='head') {
+ return this.http.head<HttpResponse<R>>(httpArgs.url, httpArgs.options);
+ } else if (lType == 'post') {
+ return this.http.post<HttpResponse<R>>(httpArgs.url, input, httpArgs.options);
}
}
@@ -97,4 +127,17 @@ export class ArchivaRequestService {
return this.translator.instant('api.' + errorMsg.error_key, parms);
}
}
+
+ public getTranslatedErrorResult(httpError : HttpErrorResponse) : ErrorResult {
+ let errorResult = httpError.error as ErrorResult;
+ errorResult.status = httpError.status;
+ if (errorResult.error_messages!=null) {
+ for (let message of errorResult.error_messages) {
+ if (message.message==null || message.message=='') {
+ message.message = this.translateError(message);
+ }
+ }
+ }
+ return errorResult;
+ }
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
index 1792ec805..d3b8e9a87 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts
@@ -19,12 +19,14 @@
import {Injectable, OnDestroy, OnInit} from '@angular/core';
import {ArchivaRequestService} from "./archiva-request.service";
import {UserInfo} from '../model/user-info';
-import {HttpErrorResponse} from "@angular/common/http";
+import {HttpErrorResponse, HttpResponse} from "@angular/common/http";
import {ErrorResult} from "../model/error-result";
-import {Observable} from "rxjs";
+import {Observable, throwError} from "rxjs";
import {Permission} from '../model/permission';
import {PagedResult} from "../model/paged-result";
import {EntityService} from "../model/entity-service";
+import { User } from '../model/user';
+import {catchError, map} from "rxjs/operators";
@Injectable({
providedIn: 'root'
@@ -269,4 +271,11 @@ export class UserService implements OnInit, OnDestroy {
return this.rest.executeRestCall<PagedResult<UserInfo>>("get", "redback", "users", {'q':searchTerm, 'offset':offset,'limit':limit,'orderBy':orderBy,'order':order});
}
+
+ public addUser(user : User) : Observable<string> {
+ return this.rest.executeResponseCall<string>("post", "redback", "users", user).pipe(
+ catchError( ( error: HttpErrorResponse) => {
+ return throwError(this.rest.getTranslatedErrorResult(error));
+ }),map( (httpResponse : HttpResponse<string>) => httpResponse.headers.get('Location')));
+ }
}
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 02a32fd84..05843c492 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
@@ -47,7 +47,8 @@
}
},
"api" : {
- "rb.auth.invalid_credentials": "Invalid credentials given"
+ "rb.auth.invalid_credentials": "Invalid credentials given",
+ "user.password.violation.numeric" : "Password must have at least {{arg0}} numeric characters."
},
"users": {
"attributes":{
@@ -61,16 +62,20 @@
"last_login": "Last Login",
"created": "Created",
"permanent": "Permanent",
- "last_password_change": "Last Password Change"
+ "last_password_change": "Last Password Change",
+ "password": "Password",
+ "confirm_password": "Confirm Password"
},
"input" : {
"small": {
- "user_id": "Must be a unique key. No space allowed.",
+ "user_id": "Must be a unique key with at least {{minSize}} characters. No spaces allowed.",
"full_name": "This is the display name of the user"
},
"user_id": "Enter user ID",
"full_name": "Enter full user name",
- "email": "email@example.org"
+ "email": "email@example.org",
+ "password": "Enter password",
+ "confirm_password": "Confirm password"
},
"list": {
@@ -88,5 +93,10 @@
},
"form": {
"submit": "Submit"
+ },
+ "password": {
+ "violations" : {
+
+ }
}
} \ No newline at end of file