diff --git a/backend/src/main/java/de/champonthis/buntspecht/controller/validation/PasswordModelValidator.java b/backend/src/main/java/de/champonthis/buntspecht/controller/validation/PasswordModelValidator.java
index 03f2b10..e498f80 100644
--- a/backend/src/main/java/de/champonthis/buntspecht/controller/validation/PasswordModelValidator.java
+++ b/backend/src/main/java/de/champonthis/buntspecht/controller/validation/PasswordModelValidator.java
@@ -28,6 +28,7 @@ public class PasswordModelValidator implements Validator {
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_WHITESPACE = "password.rule.whitespace";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LENGTH = "password.rule.length";
+ public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LOWERCASE = "password.rule.lowercase";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE = "password.rule.uppercase";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_DIGIT = "password.rule.digit";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_SPECIAL = "password.rule.special";
@@ -52,6 +53,11 @@ public class PasswordModelValidator implements Validator {
rules.add(new LengthRule(length, 4096));
}
+ int lowercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_LOWERCASE, 1);
+ if (lowercase > 0) {
+ rules.add(new CharacterRule(EnglishCharacterData.LowerCase, lowercase));
+ }
+
int uppercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE, 1);
if (uppercase > 0) {
rules.add(new CharacterRule(EnglishCharacterData.UpperCase, uppercase));
@@ -73,7 +79,7 @@ public class PasswordModelValidator implements Validator {
if (!result.isValid()) {
for (RuleResultDetail ruleResultDetail : result.getDetails()) {
- errors.rejectValue("password", ruleResultDetail.getErrorCode());
+ errors.rejectValue("password", ruleResultDetail.getErrorCode(), ruleResultDetail.getValues(), null);
}
}
diff --git a/backend/src/main/java/de/champonthis/buntspecht/controller/validation/TurnoverValidator.java b/backend/src/main/java/de/champonthis/buntspecht/controller/validation/TurnoverValidator.java
index baf1727..2ae38b0 100644
--- a/backend/src/main/java/de/champonthis/buntspecht/controller/validation/TurnoverValidator.java
+++ b/backend/src/main/java/de/champonthis/buntspecht/controller/validation/TurnoverValidator.java
@@ -32,11 +32,11 @@ public class TurnoverValidator implements Validator {
}
if (turnover.getPrice() < 0) {
- errors.rejectValue("price", "POSITIVE_VALUE");
+ errors.rejectValue("price", "MIN");
}
if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() < 0) {
- errors.rejectValue("giftcardPrice", "POSITIVE_VALUE");
+ errors.rejectValue("giftcardPrice", "MIN");
} else if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() > turnover.getPrice()) {
errors.rejectValue("giftcardPrice", "GREATER_THAN_PRICE");
}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 1e83a72..daac779 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -19,7 +19,7 @@ import { PageNotFound } from './pages/notfound/notfound.page';
import { PageProfile } from './pages/profile/profile.page';
import { PageUnavailable } from './pages/unavailable/unavailable.page';
import { UiMain } from './ui/main/main.ui';
-import { I18nEmptyPipe, I18nPipe } from './utils/i18n.pipe';
+import { ErrorCodePipe, I18nEmptyPipe, I18nPipe } from './utils/i18n.pipe';
import { MomentPipe } from './utils/moment.pipe';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
@@ -66,32 +66,33 @@ export class XhrInterceptor implements HttpInterceptor {
@NgModule({
declarations: [
+ AppComponent,
AutofocusDirective,
+ ConfirmDialog,
+ ErrorCodePipe,
I18nPipe,
I18nEmptyPipe,
MomentPipe,
- AppComponent,
- PageTurnovers,
- PageTurnoversManage,
- PageTurnover,
PageLogin,
PageManagement,
PageNotFound,
PagePassword,
PageProfile,
+ PageTurnover,
+ PageTurnovers,
+ PageTurnoversManage,
PageUnavailable,
PageUsers,
PageUserCreate,
UiMain,
- UiTurnovers,
- ConfirmDialog
+ UiTurnovers
],
imports: [
- BrowserModule,
AppRoutingModule,
+ BrowserModule,
BrowserAnimationsModule,
- MaterialModule,
FormsModule,
+ MaterialModule,
ReactiveFormsModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, registrationStrategy: 'registerWhenStable:30000' }),
],
diff --git a/frontend/src/app/pages/password/password.page.html b/frontend/src/app/pages/password/password.page.html
index 5ded0ad..7c2acc9 100644
--- a/frontend/src/app/pages/password/password.page.html
+++ b/frontend/src/app/pages/password/password.page.html
@@ -7,21 +7,21 @@
{{'password.old' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
{{'password.new' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
{{'password.repeat' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
diff --git a/frontend/src/app/pages/password/password.page.ts b/frontend/src/app/pages/password/password.page.ts
index dd4d120..3887a77 100644
--- a/frontend/src/app/pages/password/password.page.ts
+++ b/frontend/src/app/pages/password/password.page.ts
@@ -53,9 +53,9 @@ export class PagePassword implements OnInit, OnDestroy {
this.working = false;
if (error.status == 409) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
}
for (let code in errors) {
diff --git a/frontend/src/app/pages/profile/profile.page.html b/frontend/src/app/pages/profile/profile.page.html
index 476ac97..11f7b86 100644
--- a/frontend/src/app/pages/profile/profile.page.html
+++ b/frontend/src/app/pages/profile/profile.page.html
@@ -50,14 +50,14 @@
{{'password.new' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
{{'password.repeat' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
diff --git a/frontend/src/app/pages/profile/profile.page.ts b/frontend/src/app/pages/profile/profile.page.ts
index e719bab..a6cece4 100644
--- a/frontend/src/app/pages/profile/profile.page.ts
+++ b/frontend/src/app/pages/profile/profile.page.ts
@@ -108,10 +108,10 @@ export class PageProfile implements OnInit, OnDestroy {
this.working = false;
if (error.status == 422) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
- }
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
+ }
for (let code in errors) {
this.profileForm.get(code).setErrors(errors[code]);
@@ -138,10 +138,10 @@ export class PageProfile implements OnInit, OnDestroy {
this.working = false;
if (error.status == 409) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
- }
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
+ }
for (let code in errors) {
this.passwordForm.get(code).setErrors(errors[code]);
diff --git a/frontend/src/app/pages/turnover/turnover.page.html b/frontend/src/app/pages/turnover/turnover.page.html
index 4ececb6..0ac8df6 100644
--- a/frontend/src/app/pages/turnover/turnover.page.html
+++ b/frontend/src/app/pages/turnover/turnover.page.html
@@ -25,7 +25,7 @@
{{'turnover.customer' | i18n}}
- {{'turnover.customer.error.' + error.key | i18n}}
+ {{'turnover.customer.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -33,7 +33,7 @@
{{'turnover.motif' | i18n}}
- {{'turnover.motif.error.' + error.key | i18n}}
+ {{'turnover.motif.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -42,7 +42,7 @@
{{'turnover.price.suffix' | i18n}}
- {{'turnover.price.error.' + error.key | i18n}}
+ {{'turnover.price.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -54,7 +54,7 @@
{{'turnover.giftcard.number' | i18n}}
- {{'turnover.giftcard.number.error.' + error.key | i18n}}
+ {{'turnover.giftcard.number.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -63,7 +63,7 @@
{{'turnover.price.suffix' | i18n}}
- {{'turnover.giftcard.price.error.' + error.key | i18n}}
+ {{'turnover.giftcard.price.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -72,7 +72,7 @@
{{'turnover.timeInvestment.suffix' | i18n}}
- {{'turnover.timeInvestment.error.' + error.key | i18n}}
+ {{'turnover.timeInvestment.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -80,7 +80,7 @@
{{'turnover.remark' | i18n}}
- {{'turnover.remark.error.' + error.key | i18n}}
+ {{'turnover.remark.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -88,7 +88,7 @@
{{'turnover.materialConsumption' | i18n}}
- {{'turnover.materialConsumption.error.' + error.key | i18n}}
+ {{'turnover.materialConsumption.error.' + (error.key | errorCode) | i18n:error.value}}
diff --git a/frontend/src/app/pages/turnover/turnover.page.ts b/frontend/src/app/pages/turnover/turnover.page.ts
index 2b3a5f2..9c4f684 100644
--- a/frontend/src/app/pages/turnover/turnover.page.ts
+++ b/frontend/src/app/pages/turnover/turnover.page.ts
@@ -137,10 +137,10 @@ export class PageTurnover implements OnInit {
this.working = false;
if (error.status == 422) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
- }
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
+ }
for (let code in errors) {
this.form.get(code).setErrors(errors[code]);
@@ -188,10 +188,10 @@ export class PageTurnover implements OnInit {
}
if (error.status == 409) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
- }
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
+ }
for (let code in errors) {
this.form.get(code).setErrors(errors[code]);
diff --git a/frontend/src/app/pages/users/create/users.create.page.html b/frontend/src/app/pages/users/create/users.create.page.html
index a64d9d7..54081d2 100644
--- a/frontend/src/app/pages/users/create/users.create.page.html
+++ b/frontend/src/app/pages/users/create/users.create.page.html
@@ -6,7 +6,7 @@
{{'profile.username' | i18n}}
- {{'user.error.' + error.key | i18n}}
+ {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -14,7 +14,7 @@
{{'profile.name' | i18n}}
- {{'user.error.' + error.key | i18n}}
+ {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -22,7 +22,7 @@
{{'profile.email' | i18n}}
- {{'user.error.' + error.key | i18n}}
+ {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
@@ -30,7 +30,7 @@
{{'user.password' | i18n}}
- {{'password.error.' + error.key | i18n}}
+ {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
diff --git a/frontend/src/app/pages/users/create/users.create.page.ts b/frontend/src/app/pages/users/create/users.create.page.ts
index dcbe44f..044981e 100644
--- a/frontend/src/app/pages/users/create/users.create.page.ts
+++ b/frontend/src/app/pages/users/create/users.create.page.ts
@@ -52,12 +52,13 @@ export class PageUserCreate implements OnInit {
this.working = false;
if (error.status == 409) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
}
for (let code in errors) {
+ console.log(code, errors[code]);
this.form.get(code).setErrors(errors[code]);
}
}
@@ -68,9 +69,9 @@ export class PageUserCreate implements OnInit {
this.working = false;
if (error.status == 409) {
let errors = {};
- for (let code of error.error) {
- errors[code.field] = errors[code.field] || {};
- errors[code.field][code.code] = true;
+ for (let errorObject of error.error) {
+ errors[errorObject.field] = errors[errorObject.field] || {};
+ errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
}
for (let code in errors) {
diff --git a/frontend/src/app/ui/main/main.ui.ts b/frontend/src/app/ui/main/main.ui.ts
index 44ca97c..664cdc9 100644
--- a/frontend/src/app/ui/main/main.ui.ts
+++ b/frontend/src/app/ui/main/main.ui.ts
@@ -22,8 +22,8 @@ export class UiMain {
opened: boolean = true;
darkTheme: boolean = false;
title = 'buntspecht';
- currentLocale: String;
- datetimeformat: String;
+ currentLocale: string;
+ datetimeformat: string;
locales;
authenticated: boolean = false;
username: string = "";
diff --git a/frontend/src/app/utils/i18n.pipe.ts b/frontend/src/app/utils/i18n.pipe.ts
index 516a63d..86da1f1 100644
--- a/frontend/src/app/utils/i18n.pipe.ts
+++ b/frontend/src/app/utils/i18n.pipe.ts
@@ -12,7 +12,10 @@ export class I18nPipe implements PipeTransform {
constructor(private i18n: I18nService) {
}
- transform(value: String, ...args: any[]): String {
+ transform(value: string, ...args: any[]): string {
+ if (args.length === 1 && Array.isArray(args[0])) {
+ args = args[0];
+ }
return this.i18n.get(value, args);
}
}
@@ -25,7 +28,17 @@ export class I18nEmptyPipe implements PipeTransform {
constructor(private i18n: I18nService) {
}
- transform(value: String, ...args: any[]): String {
+ transform(value: string, ...args: any[]): string {
return this.i18n.getEmpty(value, args);
}
+}
+
+@Pipe({
+ name: 'errorCode'
+})
+export class ErrorCodePipe implements PipeTransform {
+
+ transform(value: string): string {
+ return value && value.toUpperCase().replaceAll('-', '_') || value;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/assets/i18n/de-informal.json b/frontend/src/assets/i18n/de-informal.json
index 7f4a631..6a93dd7 100644
--- a/frontend/src/assets/i18n/de-informal.json
+++ b/frontend/src/assets/i18n/de-informal.json
@@ -63,12 +63,12 @@
".": "Passwort ändern",
"error": {
"ILLEGAL_WHITESPACE": "Bitte keine Leerzeichen verwenden.",
- "INSUFFICIENT_DIGIT": "Bitte mindestens eine Zahl eingeben.",
- "INSUFFICIENT_LOWERCASE": "Bitte mindestens einen Kleinbuchstaben eingeben.",
- "INSUFFICIENT_SPECIAL": "Bitte mindestens ein Sonderzeichen eingeben.",
- "INSUFFICIENT_UPPERCASE": "Bitte mindestens einen Großbuchstaben eingeben.",
+ "INSUFFICIENT_DIGIT": "Bitte mindestens {0} Zahl/en eingeben.",
+ "INSUFFICIENT_LOWERCASE": "Bitte mindestens {0} Kleinbuchstaben eingeben.",
+ "INSUFFICIENT_SPECIAL": "Bitte mindestens {0} Sonderzeichen eingeben.",
+ "INSUFFICIENT_UPPERCASE": "Bitte mindestens {0} Großbuchstaben eingeben.",
"NOT_MATCH": "Passwörter stimmen nicht überein.",
- "TOO_SHORT": "Bitte ein längeres Passwort wählen.",
+ "TOO_SHORT": "Bitte Mindestens {0} Zeichen verwenden.",
"UNAUTHORIZED": "Falsches Passwort"
},
"old": "Altes Password",
@@ -108,7 +108,7 @@
"customer": {
".": "Kunde",
"error": {
- "required": "Angabe von Kunde erforderlich"
+ "REQUIRED": "Angabe von Kunde erforderlich"
}
},
"dueDate": {
@@ -122,14 +122,13 @@
"giftcard": {
".": "Gutschein",
"number": {
- ".": "Gutscheinnummer",
- "error": ""
+ ".": "Gutscheinnummer"
},
"price": {
".": "Gutscheinwert",
"error": {
"GREATER_THAN_PRICE": "Gutscheinwert übersteigt Preis",
- "min": "Üngültiger Wert"
+ "MIN": "Üngültiger Wert"
}
},
"priceUsage": "Gutscheinanteil"
@@ -139,14 +138,14 @@
"motif": {
".": "Motiv",
"error": {
- "required": "Angabe von Motiv erforderlich"
+ "REQUIRED": "Angabe von Motiv erforderlich"
}
},
"price": {
".": "Preis",
"error": {
- "min": "Üngültiger Wert",
- "required": "Angabe des Preises erforderlich"
+ "MIN": "Üngültiger Wert",
+ "REQUIRED": "Angabe des Preises erforderlich"
},
"suffix": "€",
"total": "Umsatz: {0} €"
@@ -156,7 +155,7 @@
"timeInvestment": {
".": "Zeiteinsatz",
"error": {
- "min": "Üngültiger Wert"
+ "MIN": "Üngültiger Wert"
},
"suffix": "Std.",
"total": "Zeiteinsatz: {0} Std."
@@ -199,7 +198,8 @@
"create": "Neuen User erstellen",
"delete": "User löschen",
"error": {
- "ALREADY_EXISTS": "User existiert bereits"
+ "ALREADY_EXISTS": "User existiert bereits",
+ "REQUIRED": "Angabe eines Usernames erforderlich"
},
"manage": "Verwalten",
"password": "Passwort",