[DEV] many update and corect securityu fail n set parameters

This commit is contained in:
Edouard DUPIN 2023-02-12 23:59:43 +01:00
parent e1bb3a3ab9
commit dd936c2e94
20 changed files with 492 additions and 319 deletions

View File

@ -27,7 +27,7 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.3.1</version>
<version>0.3.2</version>
</dependency>
<!-- testing -->
<dependency>

View File

@ -11,8 +11,8 @@ public class WebLauncherLocal {
// for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:15080/karso/api/";
ConfigBaseVariable.dbPort = "3306";
ConfigBaseVariable.dbType = "sqlite";
ConfigBaseVariable.dbHost = "./bdd_base.sqlite";
//ConfigBaseVariable.dbType = "sqlite";
//ConfigBaseVariable.dbHost = "./bdd_base.sqlite";
}
WebLauncher.main(args);

View File

@ -72,7 +72,7 @@ public class SystemConfigResource {
}
@PUT
@Path("key/{key}")
@RolesAllowed(value= {"USER", "ADMIN"})
@RolesAllowed(value= {"ADMIN"})
@Consumes(MediaType.APPLICATION_JSON)
public Response setKey(@Context SecurityContext sc, @PathParam("key") String key, String jsonRequest) throws Exception {
Settings res = null;
@ -90,7 +90,7 @@ public class SystemConfigResource {
JsonNode value = root.findPath("value");
res.value = value.asText();
System.out.println(" update valu : " + res.value);
SqlWrapper.update(res, res.id, List.of("value"));
return Response.status(201).entity("{ \"value\":\"" + res.value + "\"}").build();
}

View File

@ -42,7 +42,7 @@ import {
UserService,
} from 'common/service';
import { CommonModule } from '@angular/common';
import { ErrorComponent, PopInComponent, SpinerComponent, TopMenuComponent, UploadFileComponent, PasswordEntryComponent, EntryComponent, AsyncActionStatusComponent, ErrorMessageStateComponent, CheckboxComponent, BurgerPropertyComponent, EntryValidatorComponent, RenderSettingsComponent, RenderFormComponent } from 'common/component';
import { ErrorComponent, PopInComponent, SpinerComponent, TopMenuComponent, UploadFileComponent, PasswordEntryComponent, EntryComponent, AsyncActionStatusComponent, ErrorMessageStateComponent, CheckboxComponent, BurgerPropertyComponent, EntryValidatorComponent, RenderSettingsComponent, RenderFormComponent, EntryNumberComponent } from 'common/component';
import { ForbiddenScene } from 'common/scene';
import { AdminUserService, ApplicationService, ApplicationTokenService, SettingsService } from 'app/service';
import { PopInUploadProgress, PopInDeleteConfirm } from 'common/popin';
@ -63,6 +63,7 @@ import { PopInUploadProgress, PopInDeleteConfirm } from 'common/popin';
BurgerPropertyComponent,
RenderSettingsComponent,
RenderFormComponent,
EntryNumberComponent,
PopInComponent,
PopInUploadProgress,

View File

@ -5,72 +5,19 @@
<name>Application properties</name>
<description>Update property of the application:</description>
<body>
<table width="100%">
<tr>
<td width="25%"><b>id:</b></td>
<td width="75%">{{application?.id}}</td>
</tr>
<tr>
<td><b>Name:</b></td>
<td>
<app-entry
[value]="application?.name"
placeholder="Enter application name"
[hasError]="nameState !== true"
(changeValue)="checkName($event)"></app-entry>
<app-error-message-state [value]="nameState"></app-error-message-state>
</td>
</tr>
<tr>
<td><b>Description:</b></td>
<td>
<app-entry
[value]="application?.description"
(changeValue)="updateDescription($event)"></app-entry>
</td>
</tr>
<tr>
<td><b>Redirect (http://):</b></td>
<td>
<app-entry
[value]="application?.redirect"
placeholder="Enter http redirect adresses "
[hasError]="redirectState !== true"
(changeValue)="checkRedirect($event)"></app-entry>
<app-error-message-state [value]="redirectState"></app-error-message-state>
</td>
</tr>
<tr>
<td><b>Redirect development (http://):</b></td>
<td>
<app-entry
[value]="application?.redirectDev"
(changeValue)="updateRedirectDev($event)"></app-entry>
</td>
</tr>
<tr>
<td><b>Notification address (http://):</b></td>
<td>
<app-entry
[value]="application?.notification"
(changeValue)="updateNotification($event)"></app-entry>
</td>
</tr>
<tr>
<td><b>TTL (seconds before expiration):</b></td>
<td>
<app-entry
[value]="application?.ttl"
(changeValue)="updateTTL($event)"></app-entry>
</td>
</tr>
</table>
<spiner *ngIf="editApplicationMenu===undefined"></spiner>
<app-render-form
*ngIf="editApplicationMenu!==undefined"
[values]="editApplicationMenu"
(deltaValues)="onEditValues($event)"
(changeState)="onEditState($event)"
></app-render-form>
</body>
<footer>
<button
class="button login color-button-validate color-shadow-black"
id="create-button"
[disabled]="validateButtonCreateApplicationDisabled"
[disabled]="updateButtonDisabled !== 0"
(click)="onUpdateApplication()"
type="submit">
Update
@ -108,41 +55,28 @@
</tr>
</table>
</body>
</burger-property>
</div>
<div class="clear"><br/></div>
<div style="padding-top:15px;">
<burger-property>
<name>Add Token</name>
<body>
<app-render-form
[values]="createTokenMenu"
(deltaValues)="onCreateValueDeltaValues($event)"
(changeState)="onCreateValueState($event)"
></app-render-form>
</body>
<footer>
<table>
<tr>
<td width="25%">Name/Descriptiion token:</td>
<td>
<app-entry-validator
[value]="tokenName"
placeholder="Enter the token name / decription"
(checker)="checkTokenName($event)"
(changeValue)="newTokenName($event)"></app-entry-validator>
</td>
</tr>
<tr>
<td>Validity time (in day)</td>
<td>
<app-entry-validator
[value]="tokenTTL"
placeholder="Enter the Time To Lead (in day)"
(checker)="checkTokenTTL($event)"
(changeValue)="newTokenTTL($event)"></app-entry-validator>
</td>
</tr>
<tr>
<td></td>
<td>
<button
class="button login color-button-validate color-shadow-black"
id="create-button"
(click)="createToken()"
type="submit">
+ Create new Token
</button>
</td>
</tr>
</table>
<button
class="button login color-button-validate color-shadow-black"
id="create-button"
(click)="createToken()"
[disabled]="createTokenDisabled !== 0"
type="submit">
+ Create new Token
</button>
</footer>
</burger-property>
</div>

View File

@ -9,9 +9,9 @@ import { ActivatedRoute } from '@angular/router';
import { ApplicationService, ApplicationModel, ApplicationTokenService } from 'app/service';
import { ApplicationTokenModel } from 'app/service/application-token';
import { AsyncActionState } from 'common/component';
import { CheckerParameter } from 'common/component/entry-validator/entry-validator';
import { CheckerParameterType, SettingsItem, SettingType } from 'common/component/render-settings/render-settings';
import { NotificationService, PopInService } from 'common/service';
import { isNumeric } from 'common/utils';
import { isNumber, isNumeric, isString } from 'common/utils';
@Component({
selector: 'application-setting-edit',
@ -42,9 +42,9 @@ export class ApplicationEditScene implements OnInit {
.then((response: ApplicationModel) => {
console.log(`??? get full response: ${JSON.stringify(response, null, 4)}`);
self.application = response;
self.applicationRef = { ...response };
self.checkName(self.application.name);
self.checkRedirect(self.application.redirect);
//self.checkRedirect(self.application.redirect);
this.configureEditInput();
})
.catch((error: any) => {
console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`);
@ -58,133 +58,143 @@ export class ApplicationEditScene implements OnInit {
.catch((error: any) => {
console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`);
});
this.configureInput();
}
formatTimestamp(unix_timestamp: number) {
return new Date(unix_timestamp).toISOString().replace("T", " ").replace("Z", " GMT").replace(".000", "");
}
updateDescription(newValue: string): void {
this.application.description = newValue;
this.updateButtonVisibility();
}
updateRedirectDev(newValue: string): void {
this.application.redirectDev = newValue;
this.updateButtonVisibility();
}
updateNotification(newValue: string): void {
this.application.notification = newValue;
this.updateButtonVisibility();
}
updateTTL(newValue: string): void {
if (isNumeric(newValue)) {
this.application.ttl = Number(newValue);
}
this.updateButtonVisibility();
}
public nameState: boolean|string = false;
public redirectState: boolean|string = false;
public validateButtonCreateApplicationDisabled: boolean = true;
/**
* update the state of the validation button. if all is OK, the button will became clickable
*/
updateButtonVisibility(): void {
if ( ! (this.nameState === true && this.redirectState === true ) ) {
this.validateButtonCreateApplicationDisabled = true;
return;
}
if (this.application.name !== this.applicationRef.name) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
if (this.application.description !== this.applicationRef.description) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
if (this.application.redirect !== this.applicationRef.redirect) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
if (this.application.redirectDev !== this.applicationRef.redirectDev) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
if (this.application.notification !== this.applicationRef.notification) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
if (this.application.ttl !== this.applicationRef.ttl) {
this.validateButtonCreateApplicationDisabled = false;
return;
}
this.validateButtonCreateApplicationDisabled = true;
}
/**
* Check the login writing rules
*/
checkName(newValue: string): void {
this.application.name = newValue;
if (this.application?.name?.length < 6) {
this.nameState = "This name is too small >=6.";
}
this.nameState = true;
this.updateButtonVisibility();
editApplicationMenu: SettingsItem[] = undefined;
// this permit to clear the input menu...
configureEditInput() {
this.editApplicationMenu = [
{
type: SettingType.VALUE,
title: 'ID:',
value: this.application?.id,
},
{
type: SettingType.STRING,
title: 'Name:',
placeholder: 'Enter application name',
key: 'name',
value: this.application?.name,
checker: (value) => { return this.checkName(value)},
require: true,
},
{
type: SettingType.STRING,
title: 'Description:',
key: 'description',
value: this.application?.description,
},
{
type: SettingType.STRING,
title: 'Redirect:',
description:"Redirect when login (http://):",
placeholder: 'Enter http redirect adresses',
key: 'redirect',
value: this.application?.redirect,
checker: (value: CheckerParameterType) => { return this.checkRedirect(value)},
require: true,
},
{
type: SettingType.STRING,
title: 'Redirect (dev):',
description:"Redirect development (http://):",
placeholder: 'Enter http redirect adresses',
key: 'redirectDev',
value: this.application?.redirectDev,
},
{
type: SettingType.STRING,
title: 'Notification:',
description:"Redirect development (http://):",
placeholder:"http://xxx/sso-event",
key: 'notification',
value: this.application?.notification,
},
{
type: SettingType.NUMBER,
title: 'TTL:',
description: 'Time in seconds of the validity of the token',
placeholder: "888",
key: 'ttl',
value: this.application?.ttl,
checker: (value: CheckerParameterType) => { return this.checkTTL(value)},
require: true,
},
];
this.updateButtonDisabled = undefined;
this.dataUpdate = {};
}
/**
* Check the login writing rules
* Check the redirection have a good form
*/
checkRedirect(newValue: string): void {
this.application.redirect = newValue;
this.redirectState = true;
if (this.application?.redirect?.length <= 5) {
this.redirectState = "This redirect is too small.";
checkRedirect(value: CheckerParameterType): string | undefined {
if (!isString(value)) {
return "must be a string";
}
this.updateButtonVisibility();
if (value.length <= 5) {
return "This redirect is too small.";
}
return undefined;
}
updateButtonDisabled: number | undefined = undefined;
dataUpdate: object = {}
onEditState(value: number) {
console.log(`changeState : ${JSON.stringify(value, null, 2)}`);
this.updateButtonDisabled = value;
// we do not change the main ref ==> notify angular that something have change and need to be re-render???
this.cdr.detectChanges();
}
onEditValues(value: any) {
console.log(`onDeltaValues : ${JSON.stringify(value, null, 2)}`);
this.dataUpdate = value;
// we do not change the main ref ==> notify angular that something have change and need to be re-render???
this.cdr.detectChanges();
}
createState: string | boolean = undefined;
updateState: string | boolean = undefined;
/**
* Request the creation of a new application.
*/
onUpdateApplication(): void {
console.log(`create user:`);
this.createState = AsyncActionState.LOADING;
this.updateState = AsyncActionState.LOADING;
let self = this;
/*
this.applicationService.create(this.name, this.redirect)
this.applicationService.update(this.id, this.dataUpdate)
.then(
(data: ApplicationModel) => {
self.createState = AsyncActionState.DONE;
console.log(`Get new user: ${JSON.stringify(data, null, 2)}`);
////////self.applications.push(data);
self.cdr.detectChanges();
self.name = null;
self.redirect = null;
self.updateState = AsyncActionState.DONE;
console.log(`Get new application data: ${JSON.stringify(data, null, 2)}`);
self.application = data;
self.configureEditInput()
setTimeout(() => {
this.createState = undefined;
this.updateState = undefined;
}, 3000);
}
).catch(
(error: any) => {
self.createState = AsyncActionState.FAIL;
self.updateState = AsyncActionState.FAIL;
setTimeout(() => {
self.createState = undefined;
self.updateState = undefined;
}, 3000);
}
);
*/
}
createToken(): void {
let self = this;
this.applicationTokenService
.create(this.id, this.tokenName, this.tokenTTL)
.create(this.id, this.dataCreateApplication["name"], this.dataCreateApplication["ttl"])
.then((response: ApplicationTokenModel) => {
console.log(`??? get fullllllll response: ${JSON.stringify(response, null, 4)}`);
//console.log(`??? get fullllllll response: ${JSON.stringify(response, null, 4)}`);
self.tokens.push(response);
response.token = `"${response.id}:${response.token}"`
self.cdr.detectChanges();
@ -228,64 +238,75 @@ export class ApplicationEditScene implements OnInit {
}
}
createFrom = [
{
title: "Name/Description token",
placeholder: "Enter the token name / decription",
value: "",
type: "INPUT",
checker: this.checkTokenName,
},
{
title: "Validity time (in day)",
placeholder: "Enter the Time To Lead (in day)",
value: "",
checker: this.checkTokenName,
},
];
tokenName: string = undefined;
tokenTTL: number = undefined;
tokenCreateErrorCount: number = 2;
newTokenName(newValue: string) {
this.tokenName = newValue;
}
checkTokenName(chekParam: CheckerParameter): void {
if (chekParam.value.length < 3) {
chekParam.result("Must have 3 chars");
return;
}
chekParam.result(true);
}
createTokenMenu: SettingsItem[] = []
newTokenTTL(newValue: string) {
if (isNumeric(newValue)) {
this.tokenTTL = Number(newValue);
}
// this permit to clear the input menu...
configureInput() {
this.createTokenMenu = [
{
type: SettingType.STRING,
title: 'Token name:',
placeholder: 'Enter the token name / decription',
key: 'name',
value: '',
checker: (value: CheckerParameterType) => { return this.checkName(value)},
require: true,
},
{
type: SettingType.NUMBER,
title: 'Token TTL:',
placeholder: 'Enter the Time To Lead (in day)',
key: 'ttl',
value: '',
checker: (value: CheckerParameterType) => { return this.checkTTL(value)},
require: true,
},
];
}
checkTokenTTL(chekParam: CheckerParameter): void {
if (!isNumeric(chekParam.value)) {
chekParam.result("Must be a number");
return;
public createTokenDisabled: number = undefined;
public dataCreateApplication: object = {};
/**
* Check the application name is available
*/
checkName(value: CheckerParameterType): string | undefined {
if (!isString(value)) {
return "Must be a String";
}
if (chekParam.value.length<1) {
chekParam.result("Minimum one day");
return;
if (value.length < 3) {
return "This name is too small >=3.";
}
let value = Number(chekParam.value);
if (value<0) {
chekParam.result("Value must be > 0");
return;
}
if (value===0) {
chekParam.result("This have no need to create token");
return;
}
chekParam.result(true);
return undefined;
}
/**
* Check the redirection have a good form
*/
checkTTL(value: CheckerParameterType): string | undefined {
if (!isNumber(value)) {
return "Must be a number";
}
const tokenTTL = Number(value);
if (tokenTTL < 1) {
return "Minimum one day";
}
return undefined;
}
onCreateValueState(value: number) {
console.log(`changeState : ${JSON.stringify(value, null, 2)}`);
this.createTokenDisabled = value;
// we do not change the main ref ==> notify angular that something have change and need to be re-render???
this.cdr.detectChanges();
}
onCreateValueDeltaValues(value: any) {
console.log(`onDeltaValues : ${JSON.stringify(value, null, 2)}`);
this.dataCreateApplication = value;
// we do not change the main ref ==> notify angular that something have change and need to be re-render???
this.cdr.detectChanges();
}
}

View File

@ -11,7 +11,7 @@
<th>name</th>
<th>Description</th>
<th>redirect</th>
<th>TTL</th>
<th>TTL (min)</th>
<th>Notification</th>
<th>Actions</th>
</tr>

View File

@ -8,8 +8,9 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@
import { Router } from '@angular/router';
import { ApplicationService, ApplicationModel } from 'app/service';
import { AsyncActionState } from 'common/component';
import { SettingsItem, SettingType } from 'common/component/render-settings/render-settings';
import { CheckerParameterType, SettingsItem, SettingType } from 'common/component/render-settings/render-settings';
import { NotificationService, PopInService } from 'common/service';
import { isString } from 'common/utils';
@Component({
selector: 'application-setting',
@ -113,7 +114,10 @@ export class ApplicationsScene implements OnInit {
/**
* Check the application name is available
*/
checkName(value: string): string | undefined {
checkName(value: CheckerParameterType): string | undefined {
if (!isString(value)) {
return "must be a string";
}
console.log(`input value : ${value}`)
if (value.length < 6) {
return "This name is too small >=6.";
@ -130,7 +134,10 @@ export class ApplicationsScene implements OnInit {
/**
* Check the redirection have a good form
*/
checkRedirect(value: string): string | undefined {
checkRedirect(value: CheckerParameterType): string | undefined {
if (!isString(value)) {
return "must be a string";
}
if (value.length <= 5) {
return "This redirect is too small.";
}

View File

@ -5,7 +5,9 @@
<name>{{data.title}}</name>
<description>{{data.description}}</description>
<body>
<spiner *ngIf="data.values===undefined"></spiner>
<app-render-settings
*ngIf="data.values!==undefined"
[values]="data.values"
(deltaValues)="onDeltaValues($event, data)"
(changeState)="onState($event, data)"

View File

@ -9,16 +9,11 @@ import { ActivatedRoute } from '@angular/router';
import { SettingsService } from 'app/service';
import { isSettingsItem, SettingsItem, SettingType } from 'common/component/render-settings/render-settings';
import {
isArrayOf,
isBoolean,
isInArray,
isNullOrUndefined,
isNumber,
isObject,
isOptionalArrayOf,
isOptionalOf,
isString,
isUndefined,
} from 'common/utils';
@ -35,6 +30,8 @@ export interface SettingsItem222 {
newValues?: object;
// local state: if undefined => no change, otherwise the number of wrong values.
state?: number;
// values get from the server.
serverValues?: object;
}
export function isSettingsItem222(data: any): data is SettingsItem222 {
@ -75,47 +72,58 @@ export class SettingsScene implements OnInit {
{
title: 'Authentication:',
description: 'Manage the right of access to the web-services',
values: [
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-in',
description: 'Enable User to sign-in (only authorize administrators).',
key: 'SIGN_IN_ENABLE',
value: true,
},
{
type: SettingType.LINE,
},
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-up',
description: 'Enable unregister user to sign-up (register) on this web-site.',
key: 'SIGN_UP_ENABLE',
value: false,
},
{
type: SettingType.STRING,
title: 'Sign-up e-mail filter',
description: 'Specify the e-mail filtering to sign-up (regex).',
key: 'SIGN_UP_FILTER',
value: '^.*$',
},
{
type: SettingType.BOOLEAN,
title: 'e-mail validation required',
description: 'Force-user to validate his e-mail to access on service.',
key: 'EMAIL_VALIDATION_REQUIRED',
value: false,
},
],
values: undefined,
},
];
// this permit to clear the input menu...
configureEditInput() {
const root = this.menu[0];
root.values = [
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-in',
description: 'Enable User to sign-in (only authorize administrators).',
key: 'SIGN_IN_ENABLE',
value: root.serverValues["SIGN_IN_ENABLE"],
},
{
type: SettingType.LINE,
},
{
type: SettingType.BOOLEAN,
title: 'Enable Sign-up',
description: 'Enable unregister user to sign-up (register) on this web-site.',
key: 'SIGN_UP_ENABLE',
value: root.serverValues["SIGN_UP_ENABLE"],
},
{
type: SettingType.STRING,
title: 'Sign-up e-mail filter',
description: 'Specify the e-mail filtering to sign-up (regex).',
key: 'SIGN_UP_FILTER',
value: root.serverValues["SIGN_UP_FILTER"],
},
{
type: SettingType.BOOLEAN,
title: 'e-mail validation required',
description: 'Force-user to validate his e-mail to access on service.',
key: 'EMAIL_VALIDATION_REQUIRED',
value: root.serverValues["EMAIL_VALIDATION_REQUIRED"],
},
],
this.menu[0].state = undefined;
this.menu[0].newValues = {};
}
ngOnInit() {
this.settingService
.gets(['SIGN_IN_ENABLE', 'SIGN_UP_ENABLE', 'SIGN_UP_FILTER', 'EMAIL_VALIDATION_REQUIRED'])
.then((response: object) => {
console.log(`??? get full response: ${JSON.stringify(response, null, 4)}`);
this.menu[0].serverValues = response;
this.configureEditInput();
})
.catch((error: any) => {
console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`);
@ -165,6 +173,7 @@ export class SettingsScene implements OnInit {
onUpdate(elem: SettingsItem222) {
this.settingService.sets(elem.newValues)
.then((result: object) => {
// TODO ...
//multipleResponse.add(key, result);
})
.catch((error: any) => {

View File

@ -173,6 +173,26 @@ export class ApplicationService {
});
});
}
update(id: number, updateState: object): Promise<ApplicationModel> {
return new Promise((resolve, reject) => {
this.http
.requestJson({
server: 'karso',
endPoint: `application/${id}`,
requestType: HTTPRequestModel.PUT,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body:updateState,
})
.then((response: ModelResponseHttp) => {
// TODO: check type ...
resolve(response.data);
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
}
create(name: string, redirect: string): Promise<ApplicationModel> {
let body = {

View File

@ -0,0 +1,15 @@
<div class="top">
<input
type="text"
[placeholder]="placeholder===undefined?'':placeholder"
required=""
[style.border]="hasError||notANumber? '2px dashed red' : ''"
[(ngModel)]="value"
(input)="onChangeValue($event.target.value)" />
<button class="eye-button-2 unselectable" tabindex="-1" (click)="onDecrement()" type="submit">
<i class="material-icons">arrow_back_ios</i>
</button>
<button class="eye-button unselectable" tabindex="-1" (click)="onIncrement()" type="submit">
<i class="material-icons">arrow_forward_ios</i>
</button>
</div>

View File

@ -0,0 +1,39 @@
input {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
z-index: 5;
}
.eye-button {
margin-left: -44px;
margin-top: 15px;
float: right;
position: relative;
display: block;
border: none;
z-index: 15;
background: none;
padding: 4 1 13 1;
:hover {
background: none;
color: red;
}
}
.eye-button-2 {
margin-left: -70px;
margin-top: 12px;
float: right;
position: relative;
display: block;
border: none;
z-index: 15;
background: none;
padding: 4px 30px 4px 1px;
:hover {
background: none;
color: red;
}
}

View File

@ -0,0 +1,70 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { isNumeric } from 'common/utils';
@Component({
selector: 'app-entry-number',
templateUrl: 'entry-number.html',
styleUrls: ['entry-number.less'],
})
export class EntryNumberComponent implements OnInit {
/// Value of the password
@Input() value: string|undefined = '';
/// Placeholder of the Value
@Input() placeholder: string|undefined = '';
/// The element has an error
@Input() hasError: boolean = false;
/// event when change the value of the password
@Output() changeValue: EventEmitter<number|undefined> = new EventEmitter();
public notANumber: boolean = false;
ngOnInit(): void {
//if (value)
}
/**
* When input value change, need update the display and change the internal value.
* @param newValue New value set on the password
*/
onChangeValue(newValue: string): void {
if (newValue === "") {
this.value = undefined;
this.notANumber = false;
this.changeValue.emit(undefined);
return;
}
this.value = newValue;
this.notANumber = false;
if (!isNumeric(this.value)) {
this.notANumber = true;
}
const numValue = Number(this.value);
this.changeValue.emit(numValue);
}
onIncrement() {
this.notANumber = false;
let newValue = undefined;
if (!isNumeric(this.value)) {
newValue = 0;
} else {
newValue = Number(this.value) + 1;
}
this.value = "" + newValue;
this.changeValue.emit(newValue);
}
onDecrement() {
this.notANumber = false;
let newValue = undefined;
if (!isNumeric(this.value)) {
newValue = 0;
} else {
newValue = Number(this.value) - 1;
}
this.value = "" + newValue;
this.changeValue.emit(newValue);
}
}

View File

@ -1,7 +1,7 @@
<div class="top">
<input
type="text"
[placeholder]="placeholder"
[placeholder]="placeholder===undefined?'':placeholder"
required=""
[style.border]="hasError? '2px dashed red' : ''"
[value]="value===undefined?'':value"

View File

@ -12,9 +12,9 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
})
export class EntryComponent implements OnInit {
/// Value of the password
@Input() value: string = '';
@Input() value: string|undefined = '';
/// Placeholder of the Value
@Input() placeholder: string = '';
@Input() placeholder: string|undefined = '';
/// The element has an error
@Input() hasError: boolean = false;
/// event when change the value of the password

View File

@ -1,6 +1,7 @@
import { AsyncActionState, AsyncActionStatusComponent } from './async-action-status/async-status-component';
import { BurgerPropertyComponent } from './burger-property/burger-property';
import { CheckboxComponent } from './checkbox/checkbox';
import { EntryNumberComponent } from './entry-number/entry-number';
import { EntryValidatorComponent } from './entry-validator/entry-validator';
import { EntryComponent } from './entry/entry';
import { ErrorMessageStateComponent } from './error-message-state/error-message-state';
@ -13,4 +14,4 @@ import { SpinerComponent } from './spiner/spiner';
import { TopMenuComponent } from './top-menu/top-menu';
import { UploadFileComponent } from './upload-file/upload-file';
export { BurgerPropertyComponent, CheckboxComponent, RenderFormComponent, RenderSettingsComponent, ErrorMessageStateComponent, AsyncActionState, AsyncActionStatusComponent, EntryValidatorComponent, PopInComponent, TopMenuComponent, UploadFileComponent, ErrorComponent, SpinerComponent, PasswordEntryComponent, EntryComponent };
export { BurgerPropertyComponent, EntryNumberComponent, CheckboxComponent, RenderFormComponent, RenderSettingsComponent, ErrorMessageStateComponent, AsyncActionState, AsyncActionStatusComponent, EntryValidatorComponent, PopInComponent, TopMenuComponent, UploadFileComponent, ErrorComponent, SpinerComponent, PasswordEntryComponent, EntryComponent };

View File

@ -1,7 +1,7 @@
<div class="top">
<input
[type]="passwordVisibility?'text':'password'"
[placeholder]="placeholder"
[placeholder]="placeholder===undefined?'':placeholder"
required=""
[style.border]="hasError? '2px dashed red' : ''"
[value]="value"

View File

@ -1,23 +1,42 @@
<table width="100%">
<tr *ngFor="let elem of values">
<td width="15%" *ngIf="elem.type !== 'LINE'"
[style.color]="elem.require && elem.value.length === 0 && elem.newValue === undefined ? 'red' : ''"
><b>{{elem.title}}</b></td>
<td width="85%" *ngIf="elem.type !== 'LINE'">
<td width="15%" *ngIf="elem.type === 'STRING' || elem.type === 'PASSWORD' || elem.type === 'NUMBER'"
[style.color]="getStyleRequireError(elem)"
[style.font-weight]="elem.require === true ? 'bold' : ''"
>{{elem.title}}</td>
<td width="15%" *ngIf="elem.type === 'BOOLEAN'"
[style.color]="getStyleRequireError(elem)"
[style.font-weight]="elem.require === true ? 'bold' : ''"
>{{elem.title}}</td>
<td width="15%" *ngIf="elem.type === 'VALUE'"><b>{{elem.title}}</b></td>
<td width="85%" *ngIf="elem.type === 'VALUE'">{{elem.value}}</td>
<td width="85%" *ngIf="elem.type === 'STRING'">
<app-entry
*ngIf="elem.type === 'STRING'"
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="elem.state !== undefined"
[hasError]="checkHasError(elem)"
(changeValue)="checkParameter($event, elem)"></app-entry>
<app-password-entry
*ngIf="elem.type === 'PASSWORD'"
<app-error-message-state [value]="elem.state"></app-error-message-state>
</td>
<td width="85%" *ngIf="elem.type === 'NUMBER'">
<app-entry-number
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="elem.state !== true"
[hasError]="checkHasError(elem)"
(changeValue)="checkParameter($event, elem)"></app-entry-number>
<app-error-message-state [value]="elem.state"></app-error-message-state>
</td>
<td width="85%" *ngIf="elem.type === 'PASSWORD'">
<app-password-entry
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="checkHasError(elem)"
(changeValue)="checkParameter($event, elem)"></app-password-entry>
<app-error-message-state [value]="elem.state"></app-error-message-state>
</td>
<td width="85%" *ngIf="elem.type === 'BOOLEAN'">
<app-checkbox
*ngIf="elem.type === 'BOOLEAN'"
[value]="elem.value"
(changeValue)="checkParameter($event, elem)"></app-checkbox>
<app-error-message-state [value]="elem.state"></app-error-message-state>

View File

@ -7,20 +7,21 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
import { isBoolean, isInArray, isNullOrUndefined, isNumber, isObject, isOptionalOf, isString, isUndefined } from 'common/utils';
export type ReturnFunction = (a: boolean|string) => void;
export type CheckerParameterType = string | number | boolean | undefined;
// if string ==> the error, if undefined, it is OK
export type CheckerParameter = (value: string) => string | undefined;
export type CheckerParameter = (value: CheckerParameterType) => string | undefined;
export enum SettingType {
VALUE = 'VALUE',
LINE = 'LINE',
BOOLEAN = 'BOOLEAN',
NUMBER = 'NUMBER',
STRING = 'STRING',
PASSWORD = 'PASSWORD',
}
export function isSettingType(data: any): data is SettingType {
return isInArray(data, ['LINE', 'BOOLEAN', 'STRING', 'PASSWORD']);
return isInArray(data, ['VALUE', 'LINE', 'NUMBER', 'BOOLEAN', 'STRING', 'PASSWORD']);
}
export interface SettingsItem {
@ -101,7 +102,7 @@ export class RenderSettingsComponent {
/// event with the changed values
@Output() deltaValues: EventEmitter<any> = new EventEmitter();
createOutputValues(): any {
createOutputValues(): object {
let out = {};
//console.log(" Create values ... out ... ");
this.values.forEach( (value) => {
@ -129,16 +130,50 @@ export class RenderSettingsComponent {
checkMissing(): boolean | undefined {
let error = 0;
this.values.forEach( (value) => {
if (value.require === true && value.value === "" && isUndefined(value.newValue) ) {
error++;
this.values.forEach( (elem) => {
if (isNumber(elem.newValue)) {
if ((isUndefined(elem.newValue) && elem.value === undefined) || elem.newValue === undefined) {
error++;
}
} else {
if ((isUndefined(elem.newValue) && elem.value === "") || elem.newValue === "") {
error++;
}
}
});
return error !== 0;
}
getStyleRequireError(elem): string {
if (elem.require !== true) {
return "";
}
if (isNumber(elem.newValue)) {
//console.log(`>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Is a number : ${elem.newValue} ${elem.value}`)
if ((isUndefined(elem.newValue) && elem.value === undefined) || elem.newValue === undefined) {
return "red";
}
} else {
if ((isUndefined(elem.newValue) && elem.value === "") || elem.newValue === "") {
return "red";
}
}
return "";
}
checkParameter(newValue: string, item: SettingsItem): void {
if (!isNullOrUndefined(item.checker)) {
checkHasError(item: SettingsItem) {
if (!isUndefined(item.state)) {
return true;
}
if (item.require === true && item.value === "" && isUndefined(item.newValue)) {
return true;
}
return false;
}
checkParameter(newValue: string | number | boolean | undefined, item: SettingsItem): void {
if (isNullOrUndefined(newValue) || newValue === "") {
item.state = undefined
} else if (!isNullOrUndefined(item.checker)) {
item.state = item.checker(newValue);
}
if (item.value === newValue) {