[DEV] update new archodata and karso update

This commit is contained in:
Edouard DUPIN 2023-05-28 18:52:22 +02:00
parent b5ce560c88
commit 78663ed522
99 changed files with 3016 additions and 1426 deletions

View File

@ -20,7 +20,7 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.3.3</version>
<version>0.3.7</version>
</dependency>
</dependencies>

View File

@ -6,10 +6,15 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.kar.karideo.api.*;
import org.kar.karideo.filter.KarideoAuthenticationFilter;
import org.kar.karideo.migration.Initialization;
import org.kar.karideo.model.Media;
import org.kar.karideo.model.Season;
import org.kar.karideo.model.Series;
import org.kar.karideo.model.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource;
@ -18,9 +23,9 @@ import org.kar.archidata.catcher.FailExceptionCatcher;
import org.kar.archidata.catcher.InputExceptionCatcher;
import org.kar.archidata.catcher.SystemExceptionCatcher;
import org.kar.archidata.db.DBConfig;
import org.kar.archidata.filter.AuthenticationFilter;
import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter;
import org.kar.archidata.migration.MigrationEngine;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.archidata.util.ConfigBaseVariable;
@ -30,59 +35,68 @@ import jakarta.ws.rs.core.UriBuilder;
import java.net.URI;
public class WebLauncher {
final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
public static DBConfig dbConfig;
private WebLauncher() {
public WebLauncher() {
ConfigBaseVariable.bdDatabase = "karideo";
}
private static URI getBaseURI() {
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
}
public static void main(String[] args) {
ConfigBaseVariable.bdDatabase = "karideo";
try {
String out = "";
out += SqlWrapper.createTable(Data.class);
out += SqlWrapper.createTable(Media.class);
out += SqlWrapper.createTable(Type.class);
out += SqlWrapper.createTable(Series.class);
out += SqlWrapper.createTable(Season.class);
out += SqlWrapper.createTable(User.class);
System.out.println(out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
public void migrateDB() throws Exception {
WebLauncher.LOGGER.info("Create migration engine");
MigrationEngine migrationEngine = new MigrationEngine();
WebLauncher.LOGGER.info("Add initialization");
migrationEngine.setInit(new Initialization());
WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrate(GlobalConfiguration.dbConfig);
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
}
public static void main(String[] args) throws Exception {
WebLauncher.LOGGER.info("[START] application wake UP");
WebLauncher launcher = new WebLauncher();
launcher.migrateDB();
launcher.process();
WebLauncher.LOGGER.info("end-configure the server & wait finish process:");
Thread.currentThread().join();
WebLauncher.LOGGER.info("STOP the REST server:");
}
public void process() throws InterruptedException {
// ===================================================================
// Configure resources
// ===================================================================
ResourceConfig rc = new ResourceConfig();
// add multi-part models ..
rc.register(new MultiPartFeature());
rc.register(MultiPartFeature.class);
// global authentication system
rc.register(new OptionFilter());
rc.register(OptionFilter.class);
// remove cors ==> all time called by an other system...
rc.register(new CORSFilter());
rc.register(CORSFilter.class);
// global authentication system
rc.registerClasses(AuthenticationFilter.class);
rc.register(KarideoAuthenticationFilter.class);
// register exception catcher
rc.register(InputExceptionCatcher.class);
rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// add default resource:
rc.registerClasses(UserResource.class);
rc.registerClasses(SeriesResource.class);
rc.registerClasses(DataResource.class);
rc.registerClasses(SeasonResource.class);
rc.registerClasses(TypeResource.class);
rc.registerClasses(VideoResource.class);
rc.register(UserResource.class);
rc.register(SeriesResource.class);
rc.register(DataResource.class);
rc.register(SeasonResource.class);
rc.register(TypeResource.class);
rc.register(VideoResource.class);
rc.registerClasses(HealthCheck.class);
rc.registerClasses(Front.class);
rc.register(HealthCheck.class);
rc.register(Front.class);
// add jackson to be discover when we are ins stand-alone server
rc.register(JacksonFeature.class);

View File

@ -2,15 +2,37 @@
package org.kar.karideo;
import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
public class WebLauncherLocal {
public class WebLauncherLocal extends WebLauncher {
final Logger logger = LoggerFactory.getLogger(WebLauncherLocal.class);
private WebLauncherLocal() {}
public static void main(String[] args) throws InterruptedException {
WebLauncherLocal launcher = new WebLauncherLocal();
launcher.process();
launcher.logger.info("end-configure the server & wait finish process:");
Thread.currentThread().join();
launcher.logger.info("STOP the REST server:");
}
@Override
public void process() throws InterruptedException {
if (true) {
// for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:18080/karideo/api/";
}
WebLauncher.main(args);
try {
super.migrateDB();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
while (true) {
logger.error("Migration fail ==> waiting intervention of administrator...");
Thread.sleep(60*60*1000);
}
}
super.process();
}
}

View File

@ -5,18 +5,34 @@ import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.User;
import org.kar.karideo.model.UserKarideo;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.kar.archidata.annotation.security.RolesAllowed;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("/users")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class UserResource {
final Logger logger = LoggerFactory.getLogger(UserResource.class);
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserOut {
public long id;
public String login;
public UserOut(long id, String login) {
super();
this.id = id;
this.login = login;
}
}
public UserResource() {
}
@ -42,7 +58,7 @@ public class UserResource {
System.out.println("getUser " + userId);
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("===================================================");
System.out.println("== USER ? " + gc.user);
System.out.println("== USER ? " + gc.userByToken.name);
System.out.println("===================================================");
try {
return SqlWrapper.get(UserKarideo.class, userId);
@ -53,17 +69,14 @@ public class UserResource {
return null;
}
// curl http://localhost:9993/api/users/3
@GET
@Path("me")
@RolesAllowed("USER")
public User getMe(@Context SecurityContext sc) {
System.out.println("getMe()");
public UserOut getMe(@Context SecurityContext sc) {
logger.debug("getMe()");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("===================================================");
System.out.println("== USER ? " + gc.user);
System.out.println("===================================================");
return gc.user;
logger.debug("== USER ? {}", gc.userByToken);
return new UserOut(gc.userByToken.id, gc.userByToken.name);
}
}

View File

@ -0,0 +1,23 @@
package org.kar.karideo.filter;
import org.kar.archidata.filter.AuthenticationFilter;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.annotation.Priority;
//@PreMatching
@Provider
@Priority(Priorities.AUTHENTICATION)
public class KarideoAuthenticationFilter extends AuthenticationFilter {
final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class);
public KarideoAuthenticationFilter() {
super("karideo");
}
}

View File

@ -0,0 +1,59 @@
package org.kar.karideo.migration;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.karideo.model.Media;
import org.kar.karideo.model.Season;
import org.kar.karideo.model.Series;
import org.kar.karideo.model.Type;
public class Initialization extends MigrationSqlStep {
public static final int KARSO_INITIALISATION_ID = 1;
@Override
public String getName() {
return "Initialization";
}
public Initialization() throws Exception {
addClass(Data.class);
addClass(Media.class);
addClass(Type.class);
addClass(Series.class);
addClass(Season.class);
addClass(User.class);
addAction("""
INSERT INTO `type` (`id`, `name`, `description`) VALUES
(1, 'Documentary', 'Documentary (animals, space, earth...)'),
(2, 'Movie', 'Movie with real humans (film)'),
(3, 'Animation', 'Animation movies (film)'),
(4, 'Short movie', 'Small movies (less 2 minutes)'),
(5, 'TV show', 'TV show for old peoples'),
(6, 'Animation TV show', 'TV show for young peoples'),
(7, 'Theater', 'Theater play'),
(8, 'One man show', 'Recorded stand up'),
(9, 'Concert', 'Recorded concert'),
(10, 'Opera', 'Recorded opera');
""");
// set start increment element to permit to add after default elements
addAction("""
ALTER TABLE `data` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `media` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `type` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `series` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `season` AUTO_INCREMENT = 1000;
""");
}
}

View File

@ -1,7 +1,7 @@
{
"name": "karideo",
"version": "0.0.0",
"license": "MIT",
"license": "MPL-2",
"scripts": {
"all": "npm run build && npm run test",
"ng": "ng",
@ -9,6 +9,7 @@
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"style": "prettier --write .",
"e2e": "ng e2e"
},
"private": true,

View File

@ -10,6 +10,7 @@ import { MenuItem, MenuPosition } from 'common/model';
import { UserService, SessionService, SSOService } from 'common/service';
import { isNullOrUndefined } from 'common/utils';
import { ArianeService } from './service';
import { UserRoles222 } from 'common/service/session';
enum MenuEventType {
SSO_LOGIN = "SSO_CALL_LOGIN",
@ -180,7 +181,7 @@ export class AppComponent implements OnInit {
icon: "add_circle",
title: "Add media",
navigateTo: "upload",
enable: this.sessionService.userAdmin === true,
enable: this.sessionService.hasRight(UserRoles222.admin),
}, {
position: MenuPosition.LEFT,
icon: "settings",

View File

@ -24,25 +24,38 @@ import { PopInUploadProgress } from 'common/popin/upload-progress/upload-progres
import { PopInDeleteConfirm } from 'common/popin/delete-confirm/delete-confirm';
import { AppComponent } from './app.component';
import { HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
VideoEditScene, SeasonEditScene, SeriesEditScene } from './scene';
import {
HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
VideoEditScene, SeasonEditScene, SeriesEditScene
} from './scene';
import { TypeService, DataService, SeriesService, SeasonService, VideoService, ArianeService } from './service';
import { BddService, CookiesService, HttpWrapperService, OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome, PopInService, SessionService, SSOService, StorageService, UserService } from 'common/service';
import { ErrorViewerScene, ForbiddenScene, HomeOutScene, NotFound404Scene, SsoScene } from 'common/scene';
import { UploadScene } from './scene/upload/upload';
import { ErrorComponent, TopMenuComponent } from 'common/component';
import { AsyncActionStatusComponent, BurgerPropertyComponent, CheckboxComponent, EntryComponent, EntryNumberComponent, EntryValidatorComponent, ErrorComponent, ErrorMessageStateComponent, PasswordEntryComponent, RenderFormComponent, RenderSettingsComponent, SpinerComponent, TopMenuComponent } from 'common/component';
@NgModule({
declarations: [
AppComponent,
TopMenuComponent,
UploadFileComponent,
ElementDataImageComponent,
ElementTypeComponent,
ElementSeriesComponent,
ElementSeasonComponent,
ElementVideoComponent,
AppComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
PasswordEntryComponent,
EntryComponent,
EntryValidatorComponent,
SpinerComponent,
AsyncActionStatusComponent,
ErrorMessageStateComponent,
CheckboxComponent,
BurgerPropertyComponent,
RenderSettingsComponent,
RenderFormComponent,
EntryNumberComponent,
PopInComponent,
PopInCreateType,

View File

@ -0,0 +1,3 @@
<div>
<img height="50px" [src]="getImage()"/>
</div>

View File

@ -0,0 +1,68 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { PasswordEntryComponent } from './async-status-component';
describe('PasswordEntryComponent global test', () => {
let component: PasswordEntryComponent;
let fixture: ComponentFixture<PasswordEntryComponent>;
let input: HTMLInputElement;
let button: HTMLButtonElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PasswordEntryComponent],
}).compileComponents();
fixture = TestBed.createComponent(PasswordEntryComponent);
component = fixture.componentInstance;
input = fixture.nativeElement.querySelector('div').querySelector('input');
button = fixture.nativeElement.querySelector('div').querySelector('button');
});
it('Test mode password (default)', () => {
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
});
it('Test mode text', () => {
component.passwordVisibility = true;
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
});
it('test click on hide button', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(true);
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
}));
it('Set password', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
let tmpData = 'My beautifull Password';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
tmpData = '';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
}));
});

View File

@ -0,0 +1,37 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, Input } from '@angular/core';
export enum AsyncActionState {
IDLE = "idle",
LOADING = "loading",
DONE = "done",
FAIL = "fail",
}
@Component({
selector: 'app-async-status-component',
templateUrl: 'async-status-component.html',
styleUrls: ['async-status-component.less'],
})
export class AsyncActionStatusComponent {
/// Value of the password
@Input() value: AsyncActionState = AsyncActionState.IDLE;
public getImage(): string {
switch(this.value) {
case AsyncActionState.IDLE:
return '';
case AsyncActionState.LOADING:
return 'assets/images/load.svg';
case AsyncActionState.DONE:
return 'assets/images/validate.svg';
case AsyncActionState.FAIL:
return 'assets/images/validate-not.svg';
}
}
}

View File

@ -0,0 +1,13 @@
<div>
<div class="bmp-title">
<div class="title"><ng-content select="name"></ng-content></div>
<div class="description"><ng-content select="description"></ng-content></div>
</div>
<div class="bmp-elements">
<ng-content select="body"></ng-content>
</div>
<div class="bmp-validation">
<ng-content select="footer"></ng-content>
</div>
</div>

View File

@ -0,0 +1,78 @@
.bmp-title {
width: 80%;
border: solid;
border-width: 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 10px 10px 0px 0px;
background-color: gray;
.title {
font-size: 24px;
font-weight: bold;
line-height: 24px;
vertical-align: middle;
margin: 10px 0 10px 0;
text-align: Left;
}
.description {
font-size: 16px;
line-height: 16px;
vertical-align: middle;
margin: 10px 0 10px 0;
text-align: Left;
}
}
.bmp-elements {
width: 80%;
border: solid;
border-width: 0px 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 0px;
background-color: lightgray;
vertical-align: middle;
text-align: Left;
/*
.elem-hr {
width: 100%;
border-color: black;
border: dashed;
border-width: 1px 0 0 0;
margin: 10px auto;
}
.elem-title {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 36px;
}
.elem-description {
font-size: 14px;
margin: 0 20px 10px 50px;
font-style: italic;
}
.elem-input {
font-size: 14px;
margin: 0 20px 10px 36px;
input {
width: 100%;
}
}*/
}
.bmp-validation {
width: 80%;
border: solid;
border-width: 1px;
margin: auto;
padding: 10px 20px;
border-color: black;
border-radius: 0px 0px 10px 10px;
background-color: gray;
}

View File

@ -0,0 +1,18 @@
/** @file
* @author Edouard DUPIN
* @copyright 2020, Edouard DUPIN, all right reserved
* @license MPL-2 (see license file)
*/
import { Component } from '@angular/core';
@Component({
// moduleId: module.id.toString(),
selector: 'burger-property',
templateUrl: './burger-property.html',
styleUrls: ['./burger-property.less'],
})
export class BurgerPropertyComponent {
constructor() {}
}

View File

@ -0,0 +1,7 @@
<div class="elem-checkbox">
<input
type="checkbox"
[checked]="value"
(change)="onChange($event.target.checked)" />
{{comment}}
</div>

View File

@ -0,0 +1,6 @@
.elem-checkbox {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 10px;
}

View File

@ -0,0 +1,29 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-checkbox',
templateUrl: 'checkbox.html',
styleUrls: ['checkbox.less'],
})
export class CheckboxComponent {
/// Checkbox value
@Input() value: boolean = false;
/// Description of the checkbox
@Input() comment: string = "";
/// event when change the value of the password
@Output() changeValue: EventEmitter<boolean> = new EventEmitter();
/**
* When input value change, need update the display and change the internal value.
* @param newValue New value set on the password
*/
onChange(newValue: boolean): void {
this.value = newValue;
this.changeValue.emit(this.value);
}
}

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

@ -0,0 +1,8 @@
<div>
<app-entry
[value]="value"
[placeholder]="placeholder"
[hasError]="state !== true"
(changeValue)="check($event)"></app-entry>
<app-error-message-state [value]="state"></app-error-message-state>
</div>

View File

@ -0,0 +1,9 @@
input[type='text'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
z-index: 5;
}

View File

@ -0,0 +1,59 @@
/** @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 { isNullOrUndefined } from 'common/utils';
export type ReturnFunction = (a: boolean|string) => void;
export type CheckerParameter = {
value: string,
result: ReturnFunction
}
@Component({
selector: 'app-entry-validator',
templateUrl: 'entry-validator.html',
styleUrls: ['entry-validator.less'],
})
export class EntryValidatorComponent implements OnInit {
/// Value of the password
@Input() value: string = '';
/// Placeholder of the Value
@Input() placeholder: string = '';
/// The element has an error
@Output() checker: EventEmitter<CheckerParameter> = new EventEmitter();
/// event when change the value of the password
@Output() changeValue: EventEmitter<string> = new EventEmitter();
public state: boolean|string = false;
ngOnInit(): void {
//if (value)
}
updateStatus(value: boolean|string): void {
this.state = value
if (this.state === true) {
this.changeValue.emit(this.value);
}
}
check(newValue: string): void {
let self = this;
let lambdaCallBack = (value: boolean|string) => {self.updateStatus(value)};
this.value = newValue;
if (isNullOrUndefined(this.checker)) {
this.changeValue.emit(this.value);
return;
}
this.checker.emit({
value: newValue,
result: lambdaCallBack,
});
}
}

View File

@ -0,0 +1,9 @@
<div class="top">
<input
type="text"
[placeholder]="placeholder===undefined?'':placeholder"
required=""
[style.border]="hasError? '2px dashed red' : ''"
[value]="value===undefined?'':value"
(input)="onChangeValue($event.target.value)" />
</div>

View File

@ -0,0 +1,9 @@
input[type='text'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
z-index: 5;
}

View File

@ -0,0 +1,68 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { PasswordEntryComponent } from './entry';
describe('PasswordEntryComponent global test', () => {
let component: PasswordEntryComponent;
let fixture: ComponentFixture<PasswordEntryComponent>;
let input: HTMLInputElement;
let button: HTMLButtonElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PasswordEntryComponent],
}).compileComponents();
fixture = TestBed.createComponent(PasswordEntryComponent);
component = fixture.componentInstance;
input = fixture.nativeElement.querySelector('div').querySelector('input');
button = fixture.nativeElement.querySelector('div').querySelector('button');
});
it('Test mode password (default)', () => {
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
});
it('Test mode text', () => {
component.passwordVisibility = true;
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
});
it('test click on hide button', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(true);
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
}));
it('Set password', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
let tmpData = 'My beautifull Password';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
tmpData = '';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
}));
});

View File

@ -0,0 +1,35 @@
/** @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';
@Component({
selector: 'app-entry',
templateUrl: 'entry.html',
styleUrls: ['entry.less'],
})
export class EntryComponent 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<string> = new EventEmitter();
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 {
this.value = newValue;
this.changeValue.emit(this.value);
}
}

View File

@ -0,0 +1 @@
<div class="error color-shadow-black" *ngIf="value !== true && value !== false && value !== undefined">{{value}}</div>

View File

@ -0,0 +1,34 @@
.error {
background-color: #f44336;
position: absolute;
z-index: 10;
display: block;
max-width: 450px;
padding: 5px 8px;
margin: 2px 0 0;
font-size: 16px;
font-weight: 400;
border-style: solid;
border-width: 0px;
box-sizing: border-box;
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
margin-left: -10px;
}
}

View File

@ -0,0 +1,17 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-error-message-state',
templateUrl: 'error-message-state.html',
styleUrls: ['error-message-state.less'],
})
export class ErrorMessageStateComponent {
/// Value of the password
@Input() value: boolean|string = false;
}

View File

@ -1,3 +1 @@
<p>
error works!
</p>
<p>error works!</p>

View File

@ -9,11 +9,10 @@ import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-error',
templateUrl: './error.html',
styleUrls: [ './error.less' ]
styleUrls: ['./error.less'],
})
export class ErrorComponent implements OnInit {
constructor() {}
ngOnInit() {
}
ngOnInit() {}
}

View File

@ -1,14 +1,17 @@
import { ErrorComponent } from "./error/error";
import { PopInComponent } from "./popin/popin";
import { TopMenuComponent } from "./top-menu/top-menu";
import { UploadFileComponent } from "./upload-file/upload-file";
export {
PopInComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
};
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';
import { ErrorComponent } from './error/error';
import { PasswordEntryComponent } from './password-entry/password-entry';
import { PopInComponent } from './popin/popin';
import { RenderFormComponent } from './render-settings/render-form';
import { RenderSettingsComponent } from './render-settings/render-settings';
import { SpinerComponent } from './spiner/spiner';
import { TopMenuComponent } from './top-menu/top-menu';
import { UploadFileComponent } from './upload-file/upload-file';
export { BurgerPropertyComponent, EntryNumberComponent, CheckboxComponent, RenderFormComponent, RenderSettingsComponent, ErrorMessageStateComponent, AsyncActionState, AsyncActionStatusComponent, EntryValidatorComponent, PopInComponent, TopMenuComponent, UploadFileComponent, ErrorComponent, SpinerComponent, PasswordEntryComponent, EntryComponent };

View File

@ -0,0 +1,12 @@
<div class="top">
<input
[type]="passwordVisibility?'text':'password'"
[placeholder]="placeholder===undefined?'':placeholder"
required=""
[style.border]="hasError? '2px dashed red' : ''"
[value]="value"
(input)="onChangeValue($event.target.value)" />
<button class="eye-button unselectable" tabindex="-1" (click)="onVisibility()" type="submit">
<i class="material-icons">{{passwordVisibility?"visibility":"visibility_off"}}</i>
</button>
</div>

View File

@ -0,0 +1,25 @@
.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;
}
}
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
z-index: 5;
}

View File

@ -0,0 +1,68 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { PasswordEntryComponent } from './password-entry';
describe('PasswordEntryComponent global test', () => {
let component: PasswordEntryComponent;
let fixture: ComponentFixture<PasswordEntryComponent>;
let input: HTMLInputElement;
let button: HTMLButtonElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PasswordEntryComponent],
}).compileComponents();
fixture = TestBed.createComponent(PasswordEntryComponent);
component = fixture.componentInstance;
input = fixture.nativeElement.querySelector('div').querySelector('input');
button = fixture.nativeElement.querySelector('div').querySelector('button');
});
it('Test mode password (default)', () => {
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
});
it('Test mode text', () => {
component.passwordVisibility = true;
fixture.detectChanges();
expect(input.textContent).toEqual('');
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
});
it('test click on hide button', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(true);
expect(button.textContent).toEqual('visibility');
expect(input.type).toEqual('text');
button.click();
tick();
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
expect(button.textContent).toEqual('visibility_off');
expect(input.type).toEqual('password');
}));
it('Set password', fakeAsync(() => {
fixture.detectChanges();
expect(component.passwordVisibility).toEqual(false);
let tmpData = 'My beautifull Password';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
tmpData = '';
input.value = tmpData;
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(input.textContent).toEqual(tmpData);
expect(component.value).toEqual(tmpData);
}));
});

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-password-entry',
templateUrl: 'password-entry.html',
styleUrls: ['password-entry.less'],
})
export class PasswordEntryComponent {
/// Value of the password
@Input() value: string = '';
/// Placeholder of the Value
@Input() placeholder: string = 'Write password.';
/// The element has an error
@Input() hasError: boolean = false;
/// event when change the value of the password
@Output() changeValue: EventEmitter<string> = new EventEmitter();
/// Local value of the password viwibility
public passwordVisibility: boolean = false;
/**
* Ov visibility request change (toggle the visibility)
*/
onVisibility(): void {
this.passwordVisibility = !this.passwordVisibility;
}
/**
* 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 {
this.value = newValue;
this.changeValue.emit(this.value);
}
}

View File

@ -5,14 +5,13 @@
*/
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter } from '@angular/core';
import { PopInService } from 'common/service';
@Component({
// moduleId: module.id.toString(),
selector: 'app-popin',
templateUrl: './popin.html',
styleUrls: [ './popin.less' ]
styleUrls: ['./popin.less'],
})
export class PopInComponent implements OnInit, OnDestroy {
@Input() id: string;
@ -28,9 +27,7 @@ export class PopInComponent implements OnInit, OnDestroy {
public displayPopIn: boolean = false;
constructor(private popInService: PopInService) {
}
constructor(private popInService: PopInService) {}
ngOnInit(): void {
// ensure id attribute exists
if (!this.id) {

View File

@ -0,0 +1,47 @@
<table width="100%">
<tr *ngFor="let elem of values">
<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
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="checkHasError(elem)"
(changeValue)="checkParameter($event, elem)"></app-entry>
<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]="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
[value]="elem.value"
(changeValue)="checkParameter($event, elem)"></app-checkbox>
<app-error-message-state [value]="elem.state"></app-error-message-state>
</td>
<td width="85%" *ngIf="elem.type === 'LINE'"></td>
<td width="85%" *ngIf="elem.type === 'LINE'"></td>
</tr>
</table>

View File

@ -0,0 +1,17 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Component } from '@angular/core';
import { RenderSettingsComponent } from './render-settings';
@Component({
selector: 'app-render-form',
templateUrl: 'render-form.html',
styleUrls: ['render-form.less'],
})
export class RenderFormComponent extends RenderSettingsComponent {
}

View File

@ -0,0 +1,39 @@
<div *ngFor="let elem of values" class="settings-elements">
<div *ngIf="elem.type === 'LINE'">
<div class="elem-hr"></div>
</div>
<div *ngIf="elem.type === 'BOOLEAN'">
<div class="elem-checkbox">
<app-checkbox
[value]="elem.value"
[comment]="elem.title"
(changeValue)="checkParameter($event, elem)"></app-checkbox>
</div>
<div class="elem-description">{{elem.description}}</div>
</div>
<div *ngIf="elem.type === 'STRING'">
<div class="elem-title">{{elem.title}}</div>
<div class="elem-description">{{elem.description}}</div>
<div class="elem-input">
<app-entry
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="elem.state !== undefined"
(changeValue)="checkParameter($event, elem)"></app-entry>
<app-error-message-state [value]="elem.state"></app-error-message-state>
</div>
</div>
<div *ngIf="elem.type === 'PASSWORD'">
<div class="elem-title">{{elem.title}}</div>
<div class="elem-description">{{elem.description}}</div>
<div class="elem-input">
<input [value]="elem.value" />
<app-password-entry
[value]="elem.value"
[placeholder]="elem.placeholder"
[hasError]="elem.state !== true"
(changeValue)="checkParameter($event, elem)"></app-password-entry>
<app-error-message-state [value]="elem.state"></app-error-message-state>
</div>
</div>
</div>

View File

@ -0,0 +1,32 @@
.settings-elements {
.elem-hr {
width: 100%;
border-color: black;
border: dashed;
border-width: 1px 0 0 0;
margin: 10px auto;
}
.elem-checkbox {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 10px;
}
.elem-title {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 36px;
}
.elem-description {
font-size: 14px;
margin: 0 20px 10px 50px;
font-style: italic;
}
.elem-input {
font-size: 14px;
margin: 0 20px 10px 36px;
input {
width: 100%;
}
}
}

View File

@ -0,0 +1,204 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
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: 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, ['VALUE', 'LINE', 'NUMBER', 'BOOLEAN', 'STRING', 'PASSWORD']);
}
export interface SettingsItem {
// Type of the menu Node
type: SettingType;
// Unique key reference
key?: string;
// Displayed Title
title?: string;
// Description of the parameter
description?: string;
// placeholder of the parameter
placeholder?: string;
// Parameter key to SET/GET or the sub-menu
value?: boolean | string | Number;
// when data is change the value is set here undefined if not correct (must be set @ undefined):
newValue?: boolean | string | Number;
// checker to validate the data:
checker?: CheckerParameter
// result of the checker (must be set @ undefined):
state?: boolean | string;
// The element is require to have a valid form.
require?: boolean
}
export function isSettingsItem(data: any): data is SettingsItem {
if (isNullOrUndefined(data)) {
return false;
}
if (!isObject(data)) {
return false;
}
if (!isSettingType(data.type)) {
return false;
}
if (!isString(data.key)) {
return false;
}
if (!isOptionalOf(data.title, isString)) {
return false;
}
if (!isOptionalOf(data.description, isString)) {
return false;
}
if (!isOptionalOf(data.placeholder, isString)) {
return false;
}
if (
!isOptionalOf(data.value, isBoolean) &&
!isOptionalOf(data.value, isString) &&
!isOptionalOf(data.value, isNumber)
) {
return false;
}
if (!isUndefined(data.newValue)) {
return false;
}
if (!isOptionalOf(data.state, isString)) {
return false;
}
if (!isOptionalOf(data.require, isBoolean)) {
return false;
}
return true;
}
@Component({
selector: 'app-render-settings',
templateUrl: 'render-settings.html',
styleUrls: ['render-settings.less'],
})
export class RenderSettingsComponent {
/// Value of the password
@Input() values: SettingsItem[] = [];
/// Number of error detected (undefined: No change or not ready, else the number of error)
@Output() changeState: EventEmitter<Number> = new EventEmitter();
/// event with the changed values
@Output() deltaValues: EventEmitter<any> = new EventEmitter();
createOutputValues(): object {
let out = {};
//console.log(" Create values ... out ... ");
this.values.forEach( (value) => {
if (isNullOrUndefined(value.key)) {
return;
}
//console.log(` key: ${value.key} : ${value.newValue}`);
if (!isNullOrUndefined(value.newValue)) {
//console.log(` ==> set`);
out[value.key] = value.newValue;
}
});
return out;
}
countErrors(): number | undefined {
let out = 0;
this.values.forEach( (value) => {
if (!isUndefined(value.state)) {
out++;
}
});
return out;
}
checkMissing(): boolean | undefined {
let error = 0;
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 "";
}
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) {
item.newValue = undefined;
} else {
item.newValue = newValue;
}
const missing = this.checkMissing();
const outValue = this.createOutputValues();
const nbError = this.countErrors();
const nbValuesChanges = Object.keys(outValue).length;
//console.log(`outValue=${JSON.stringify(outValue, null, 2)}`);
//console.log(`nbError=${nbError} nbValuesChanges=${nbValuesChanges}`);
if (nbValuesChanges === 0) {
this.changeState.emit(undefined);
return;
}
if (missing === true) {
this.changeState.emit(undefined);
return;
}
this.changeState.emit(nbError);
if (nbError === 0) {
this.deltaValues.emit(outValue);
}
}
}

View File

@ -0,0 +1,14 @@
/** @file
* @author Edouard DUPIN
* @copyright 2023, Edouard DUPIN, all right reserved
* @license MPL-2 (see license file)
*/
import { Component} from '@angular/core';
@Component({
selector: 'spiner',
template: '<img height="50px" src="assets/images/load.svg"/>',
})
export class SpinerComponent {
}

View File

@ -1,80 +1,64 @@
<div class="top">
<div id="main-menu" class="main-menu color-menu-background">
<div *ngFor="let data of menu">
<div class="inert_element"
<div
class="inert_element unselectable"
*ngIf="isNotButton(data)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)">
<div class="xdesktop" *ngIf="data.icon">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div class="xdesktop" *ngIf="data.icon"><i class="material-icons">{{data.icon}}</i> {{data.title}}</div>
<div class="xmobile" *ngIf="data.icon">
<i class="material-icons">{{data.icon}}</i>
</div>
<div class="xdesktop" *ngIf="!data.icon">
{{data.title}}
<div class="xdesktop" *ngIf="!data.icon">{{data.title}}</div>
</div>
</div>
<button class="item"
<button
class="item unselectable"
*ngIf="!isNotButton(data)"
(click)="onGeneric(data, $event)"
(auxclick)="onGeneric(data, $event)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)"
[disable]="false">
<div class="avatar" *ngIf="data.image">
<img class="avatar" src="{{data.image}}"/> {{data.title}}
</div>
<div class="avatar unselectable" *ngIf="data.image"><img class="avatar" src="{{data.image}}" /> {{data.title}}</div>
<div class="xdesktop" *ngIf="data.icon && !data.image">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div class="xmobile" *ngIf="data.icon && !data.image">
<i class="material-icons">{{data.icon}}</i>
</div>
<div class="xdesktop" *ngIf="!data.icon && !data.image">
{{data.title}}
</div>
<div class="xdesktop" *ngIf="!data.icon && !data.image">{{data.title}}</div>
</button>
</div>
</div>
<div class="fill-all" *ngIf="subMenu" (click)="onOutUserProperty()">
<div class="sub-menu color-menu-background"
[ngClass]="getClassMenuPosition()">
<div class="sub-menu color-menu-background unselectable" [ngClass]="getClassMenuPosition()">
<div *ngFor="let data of subMenu">
<div class="inert_element unselectable"
<div
class="inert_element unselectable"
*ngIf="isNotButton(data)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)">
<div class="xdesktop"
*ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<div class="xdesktop" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div class="xmobile"
*ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<div class="xmobile" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i>
</div>
<div *ngIf="!data.icon"
[ngStyle]="{'float': data.position}">
{{data.title}}
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
</div>
</div>
<button class="item"
<button
class="item"
*ngIf="isEnable(data) && !isNotButton(data)"
(click)="onGeneric(data, $event)"
(auxclick)="onGeneric(data, $event)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)"
[disable]="false">
<div *ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<div *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div *ngIf="!data.icon"
[ngStyle]="{'float': data.position}">
{{data.title}}
</div>
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
</button>
</div>
</div>

View File

@ -1,5 +1,3 @@
.element-pos-left {
z-index: 5;
float: left;
@ -24,7 +22,6 @@
}
.top {
.sub-menu {
position: fixed;
min-width: 150px;
@ -63,11 +60,12 @@
vertical-align: middle;
}
/* Create an Arraw on the top ob the box ... */
&:after, &:before {
&:after,
&:before {
bottom: 100%;
right: 13px;
border: solid transparent;
content: " ";
content: ' ';
height: 0;
width: 0;
position: absolute;
@ -80,7 +78,6 @@
border-width: 15px;
margin-left: -15px;
}
}
.menu-left {
top: 75px;
@ -137,14 +134,13 @@
font-weight: bold;
font-size: 17px;
.comment {
visibility: "hidden";
visibility: 'hidden';
}
@media all and (min-width: 700px) {
.comment {
visibility: "visible";
visibility: 'visible';
}
}
}
.inert_element {

View File

@ -9,8 +9,6 @@ import { Router } from '@angular/router';
import { isNullOrUndefined } from 'common/utils';
import { MenuItem } from 'common/model/menu-item';
export interface EventOnMenu {
menu: MenuItem;
newWindows: boolean;
@ -20,7 +18,7 @@ export interface EventOnMenu {
@Component({
selector: 'app-top-menu',
templateUrl: './top-menu.html',
styleUrls: [ './top-menu.less' ]
styleUrls: ['./top-menu.less'],
})
export class TopMenuComponent implements OnInit {
@Input() menu: MenuItem[];
@ -28,14 +26,14 @@ export class TopMenuComponent implements OnInit {
subMenuPosition: String = undefined;
@Output() callback: EventEmitter<EventOnMenu> = new EventEmitter();
constructor(private router: Router) {
}
constructor(private router: Router) {}
isNotButton(data: MenuItem) {
return isNullOrUndefined(data.navigateTo)
&& (isNullOrUndefined(data.callback) || data.callback === false)
&& isNullOrUndefined(data.subMenu);
return (
isNullOrUndefined(data.navigateTo) &&
(isNullOrUndefined(data.callback) || data.callback === false) &&
isNullOrUndefined(data.subMenu)
);
}
isEnable(data: MenuItem) {
if (!isNullOrUndefined(data) && !isNullOrUndefined(data.enable) && data.enable === false) {
@ -48,22 +46,20 @@ export class TopMenuComponent implements OnInit {
return `float: ${data}`;
}
ngOnInit() {
}
ngOnInit() {}
onOutUserProperty(): void {
//console.log('onOutUserProperty ==> event...');
this.subMenu = undefined;
}
getClassMenuPosition(): string {
if (isNullOrUndefined(this.subMenuPosition)) {
return "menu-left";
return 'menu-left';
}
return 'menu-' + this.subMenuPosition;
}
getClassModel(data?: string): string {
if (isNullOrUndefined(data)) {
return "";
return '';
}
return 'model_' + data;
}
@ -73,7 +69,7 @@ export class TopMenuComponent implements OnInit {
// check if we need to navigate
if (!isNullOrUndefined(data.navigateTo)) {
// remove in every case the subMenu:
this.subMenu = undefined
this.subMenu = undefined;
this.subMenuPosition = undefined;
this.router.navigate([data.navigateTo]);
return;
@ -105,5 +101,4 @@ export class TopMenuComponent implements OnInit {
this.subMenu = data.subMenu;
this.subMenuPosition = data.position;
}
}

View File

@ -1,11 +1,9 @@
<div>
<div class="uploadfilecontainer" (click)="fileInput.click()" appDragDrop (onFileDropped)="uploadFile($event)">
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)">
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)" />
</div>
<div class="files-list" *ngFor="let file of files;let i=index">
<p>{{ file }}</p>
<button class="delete-file" (click)="deleteAttachment(i)">
// DELETE //
</button>
<button class="delete-file" (click)="deleteAttachment(i)">// DELETE //</button>
</div>
</div>

View File

@ -6,7 +6,7 @@
height: 200px;
width: 80%;
margin: 20px auto;
border: 2px dashed #1C8ADB;
border: 2px dashed #1c8adb;
border-radius: 10px;
}

View File

@ -9,7 +9,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-upload-file',
templateUrl: './upload-file.html',
styleUrls: [ './upload-file.less' ]
styleUrls: ['./upload-file.less'],
})
export class UploadFileComponent {
files: any = [];

View File

@ -1,8 +1,4 @@
import { isMenuItem, isMenuPosition, MenuItem, MenuPosition } from "./menu-item";
import { NodeData, isNodeData } from "./node";
import { isMenuItem, isMenuPosition, MenuItem, MenuPosition } from './menu-item';
import { NodeData, isNodeData } from './node';
export {
NodeData, isNodeData,
MenuPosition, isMenuPosition, MenuItem, isMenuItem,
}
export { NodeData, isNodeData, MenuPosition, isMenuPosition, MenuItem, isMenuItem };

View File

@ -1,16 +1,13 @@
import { isObject, isOptionalOf, isString, isNullOrUndefined, isOptionalArrayOf } from "common/utils";
import { isObject, isOptionalOf, isString, isNullOrUndefined, isOptionalArrayOf, isInArray } from 'common/utils';
export enum MenuPosition {
LEFT = "left",
RIGHT = "right",
CENTER = "none",
LEFT = 'left',
RIGHT = 'right',
CENTER = 'none',
}
export function isMenuPosition(data: any): data is MenuPosition {
return data === "left"
|| data === "right"
|| data === "none";
return isInArray(data, ['left', 'right', 'none']);
}
export interface MenuItem {
@ -20,24 +17,23 @@ export interface MenuItem {
hover?: string;
// Icon of the menue (need to be a meterial-icon name
icon?: string;
// If we want to display an image instead of an icon
// Displayed Title
image?: string;
// Displayed Title
title: string;
// Jump Link (If undefined: it is considered as text and not a button)
// Model of the display:
model?: string;
// Jump Link (If undefined: it is considered as text and not a button)
navigateTo?: string;
// if it request a callbak with the curent element: (not compatible with the previous)
// Menu model For a subList of elements
callback?: boolean;
// Other data that want to be set by the user
otherData?: any;
// Enable or not the elemnt
// Menu model For a subList of elements
enable?: boolean;
// Menu model For a subList of elements
subMenu?: MenuItem[];
};
}
export function isMenuItem(data: any): data is MenuItem {
if (isNullOrUndefined(data)) {

View File

@ -1,6 +1,4 @@
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from "common/utils";
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from 'common/utils';
export interface NodeData {
id: number;
@ -8,8 +6,7 @@ export interface NodeData {
description?: string;
parentId?: number;
covers?: number[];
};
}
export function isNodeData(data: any): data is NodeData {
if (!isObject(data)) {

View File

@ -1,5 +1,6 @@
<div>
<app-popin id="popin-delete-confirm"
<app-popin
id="popin-delete-confirm"
popSize="small"
popTitle="Confirm Remove"
[closeTitle]="closeButtonTitle"

View File

@ -1,15 +1,13 @@
.expand {
width: 100%;
input {
width: 100%;
};
}
div {
width: 100%;
};
}
textarea {
width: 100%;
};
}
text-align: center;
}

View File

@ -11,7 +11,7 @@ import { PopInService } from 'common/service';
@Component({
selector: 'delete-confirm',
templateUrl: './delete-confirm.html',
styleUrls: [ './delete-confirm.less' ]
styleUrls: ['./delete-confirm.less'],
})
export class PopInDeleteConfirm implements OnInit {
@Input() comment: string = null;
@ -21,17 +21,11 @@ export class PopInDeleteConfirm implements OnInit {
public closeButtonTitle: string = 'Cancel';
public validateButtonTitle: string = 'Validate';
constructor(private popInService: PopInService) {
constructor(private popInService: PopInService) {}
}
OnDestroy() {}
OnDestroy() {
}
ngOnInit() {
}
ngOnInit() {}
eventPopUp(_event: string): void {
console.log(`GET event: ${_event}`);

View File

@ -1,8 +1,4 @@
import { PopInDeleteConfirm } from "./delete-confirm/delete-confirm";
import { PopInUploadProgress } from "./upload-progress/upload-progress";
import { PopInDeleteConfirm } from './delete-confirm/delete-confirm';
import { PopInUploadProgress } from './upload-progress/upload-progress';
export {
PopInDeleteConfirm,
PopInUploadProgress,
}
export { PopInDeleteConfirm, PopInUploadProgress };

View File

@ -1,5 +1,6 @@
<div>
<app-popin id="popin-upload-progress"
<app-popin
id="popin-upload-progress"
popSize="medium"
popTitle="Upload Media File"
[closeTitle]="closeButtonTitle"
@ -13,18 +14,20 @@
<div class="progress-bar" style="width:{{progress}}%">&nbsp;&nbsp;&nbsp;{{progress}}%</div>
</div>
<div *ngIf="progress != 100">
<label class="unselectable">Upload:</label><label style="text-align: right;">{{uploadDisplay}}</label><br/>
<label class="unselectable">Size:</label><label style="text-align: right;">{{sizeDisplay}}</label>
<label class="unselectable">Upload:</label><label style="text-align: right">{{uploadDisplay}}</label><br />
<label class="unselectable">Size:</label><label style="text-align: right">{{sizeDisplay}}</label>
</div>
<div *ngIf="progress == 100 && error == null && result == null">
<label class="unselectable">Upload done ... waiting server answer</label>
</div>
<div *ngIf="error != null">
<label class="unselectable"><b>Get an error From the server:</b></label><br/>
<label class="unselectable"><b>Get an error From the server:</b></label
><br />
<label class="unselectable">{{error}}</label>
</div>
<div *ngIf="result != null">
<label class="unselectable"><b>Upload finished:</b></label><br/>
<label class="unselectable"><b>Upload finished:</b></label
><br />
<label class="unselectable">{{result}}</label>
</div>
</app-popin>

View File

@ -1,13 +1,11 @@
.expand {
width: 100%;
input {
width: 100%;
};
}
textarea {
width: 100%;
};
}
}
.progress-back {
@ -18,6 +16,6 @@
.progress-bar {
color: #000000 !important;
background-color:#4CAF50!important;
background-color: #4caf50 !important;
border-radius: 3px;
}

View File

@ -12,7 +12,7 @@ import { PopInService } from 'common/service';
@Component({
selector: 'upload-progress',
templateUrl: './upload-progress.html',
styleUrls: [ './upload-progress.less' ]
styleUrls: ['./upload-progress.less'],
})
export class PopInUploadProgress implements OnInit {
@Input() mediaTitle: string = '';
@ -26,23 +26,14 @@ export class PopInUploadProgress implements OnInit {
public uploadDisplay: string = '';
public sizeDisplay: string = '';
public progress: number = 0;
constructor(private router: Router,
private popInService: PopInService) {
}
OnDestroy() {
}
ngOnInit() {
}
constructor(private router: Router, private popInService: PopInService) {}
OnDestroy() {}
ngOnInit() {}
eventPopUp(_event: string): void {
console.log(`GET event: ${_event}`);
this.popInService.close('popin-upload-progress');
}
updateNeedSend():void {
}
updateNeedSend(): void {}
limit3(count: number): string {
if (count >= 1000) {
@ -87,7 +78,7 @@ export class PopInUploadProgress implements OnInit {
ngOnChanges(changes: SimpleChanges) {
//console.log(`Upload progress event : ${JSON.stringify(changes)}`);
this.progress = Math.trunc(this.mediaUploaded * 100 / this.mediaSize);
this.progress = Math.trunc((this.mediaUploaded * 100) / this.mediaSize);
this.uploadDisplay = this.convertInHuman(this.mediaUploaded);
this.sizeDisplay = this.convertInHuman(this.mediaSize);
if (this.error === null && this.result === null) {
@ -106,7 +97,6 @@ export class PopInUploadProgress implements OnInit {
}
}
export class UploadProgress {
labelMediaTitle: string = '';
mediaSendSize: number = 0;

View File

@ -1,6 +1,8 @@
<div class="full-mode">
<div class="centered">
<div class="error"><label class="unselectable"><i class="material-icons">report</i> 404 Not Found !</label></div>
<div class="error">
<label class="unselectable"><i class="material-icons">report</i> 404 Not Found !</label>
</div>
<div class="comment"><label class="unselectable">Unknwn this page.</label></div>
</div>
</div>

View File

@ -1,4 +1,3 @@
.full-mode {
width: 100%;
height: 100%;
@ -17,7 +16,7 @@
padding: 16px 32px 16px 32px;
top: 50%;
transform: ~"translate(0, -50%)";
transform: ~'translate(0, -50%)';
font-size: 30px;
font-weight: 600;

View File

@ -9,7 +9,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-404-not-found',
templateUrl: './404.html',
styleUrls: [ './404.less' ]
styleUrls: ['./404.less'],
})
export class NotFound404Scene {
constructor() {}

View File

@ -1,3 +1 @@
<p>
error-viewer works!
</p>
<p>error-viewer works!</p>

View File

@ -10,13 +10,10 @@ import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-error-viewer',
templateUrl: './error-viewer.html',
styleUrls: [ './error-viewer.less' ]
styleUrls: ['./error-viewer.less'],
})
export class ErrorViewerScene implements OnInit {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
ngOnInit() {}
}
}

View File

@ -1,6 +1,10 @@
<div class="full-mode">
<div class="centered">
<div class="error"><label class="unselectable"><i class="material-icons">gpp_bad</i> 403 Forbidden</label></div>
<div class="comment"><label class="unselectable">You don't have permission to access this resource.</label></div>
<div class="error">
<label class="unselectable"><i class="material-icons">gpp_bad</i> 403 Forbidden</label>
</div>
<div class="comment">
<label class="unselectable">You don't have permission to access this resource.</label>
</div>
</div>
</div>

View File

@ -1,4 +1,3 @@
.full-mode {
width: 100%;
height: 100%;
@ -18,7 +17,7 @@
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
transform: ~'translate(-50%, -50%)';
font-size: 30px;
font-weight: 600;

View File

@ -9,7 +9,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-forbidden',
templateUrl: './forbidden.html',
styleUrls: [ './forbidden.less' ]
styleUrls: ['./forbidden.less'],
})
export class ForbiddenScene {
constructor() {}

View File

@ -1,6 +1,8 @@
<div class="full-mode">
<div class="centered">
<div class="error"><label class="unselectable"><i class="material-icons">login</i> Not registered!</label></div>
<div class="error">
<label class="unselectable"><i class="material-icons">login</i> Not registered!</label>
</div>
<div class="comment"><label class="unselectable">you must login to access to this website.</label></div>
</div>
</div>

View File

@ -1,4 +1,3 @@
.full-mode {
width: 100%;
height: 100%;
@ -17,7 +16,7 @@
padding: 16px 32px 16px 32px;
top: 50%;
transform: ~"translate(0, -50%)";
transform: ~'translate(0, -50%)';
font-size: 30px;
font-weight: 600;

View File

@ -9,7 +9,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-home-out',
templateUrl: './home-out.html',
styleUrls: [ './home-out.less' ]
styleUrls: ['./home-out.less'],
})
export class HomeOutScene {
constructor() {}

View File

@ -1,16 +1,8 @@
import { ErrorViewerScene } from "./error-viewer/error-viewer";
import { ForbiddenScene } from "./forbidden/forbidden";
import { SsoScene } from "./sso/sso";
//import { UploadScene } from "../../app/scene/upload/upload";
import { HomeOutScene } from "./home-out/home-out";
import { NotFound404Scene } from "./404/404";
export {
ErrorViewerScene,
SsoScene,
ForbiddenScene,
HomeOutScene,
NotFound404Scene,
};
//import { ErrorViewerScene } from "./error-viewer/error-viewer";
import { ErrorViewerScene } from './error-viewer/error-viewer';
import { ForbiddenScene } from './forbidden/forbidden';
import { SsoScene } from './sso/sso';
import { HomeOutScene } from './home-out/home-out';
import { NotFound404Scene } from './404/404';
export { ErrorViewerScene, SsoScene, ForbiddenScene, HomeOutScene, NotFound404Scene };

View File

@ -18,10 +18,14 @@
<div class="container" *ngIf="token === 'ERROR_ME'">
<label for="login_field"><b>ERROR: </b> can not retreive user local informations!</label>
</div>
<div class="container" *ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
<div
class="container"
*ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
<label for="login_field"><b>Connected: </b> Redirect soon!</label>
</div>
<div class="container" *ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
<div
class="container"
*ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
<label for="login_field"><b>Welcome back: </b> {{userName}}</label>
</div>
</div>

View File

@ -1,4 +1,3 @@
.full {
width: 100%;
height: 100%;
@ -10,7 +9,8 @@
display: block;
}
input[type=text], input[type=password] {
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
@ -33,7 +33,6 @@ input[type=text], input[type=password] {
margin: 15px 0 0 0;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
@ -58,7 +57,7 @@ span.psw {
}
.forgot {
color: #00B;
color: #00b;
font-size: 14px;
float: right;
buttum: 0;
@ -78,11 +77,12 @@ span.psw {
border-width: 0px;
box-sizing: border-box;
&:after, &:before {
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: " ";
content: ' ';
height: 0;
width: 0;
position: absolute;
@ -96,7 +96,6 @@ span.psw {
}
}
.container-global {
position: relative;
max-width: 400px;
@ -104,6 +103,6 @@ span.psw {
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -11,20 +11,21 @@ import { SSOService, UserService } from 'common/service';
@Component({
selector: 'app-sso',
templateUrl: './sso.html',
styleUrls: [ './sso.less' ]
styleUrls: ['./sso.less'],
})
export class SsoScene implements OnInit {
ssoData: string;
token: string;
keepConnected: boolean
userName: string
keepConnected: boolean;
userName: string;
constructor(
private router: Router,
private route: ActivatedRoute,
private ssoService: SSOService,
private userService: UserService) {
console.error("retreive data after SSO");
private userService: UserService
) {
console.error('retreive data after SSO');
}
ngOnInit() {
@ -52,21 +53,24 @@ export class SsoScene implements OnInit {
console.log(`token: '${token}'`);
console.log(`keepConnected: '${keepConnected}'`);
if (this.token !== '__CANCEL__' && this.token !== '__FAIL__' && this.token !== '__LOGOUT__') {
const destination = (this.ssoData);
const destination = this.ssoData;
console.log(`ssoData (decoded): '${destination}'`);
const realDst = this.ssoService.unHashLocalData(destination);
console.log(`realDst: '${realDst}'`);
this.userService.startSession(this.token, this.keepConnected).then((userName: string) => {
this.userService
.startSession(this.token, this.keepConnected)
.then((userName: string) => {
self.userName = userName;
setTimeout(function () {
self.router.navigate([realDst], { replaceUrl: true });
}, 500); // 2 seconds
}).catch(() => {
this.token = "ERROR_ME";
})
.catch(() => {
this.token = 'ERROR_ME';
});
} else if (this.token === '__LOGOUT__') {
this.userService.removeSession();
const destination = (this.ssoData);
const destination = this.ssoData;
console.error(`ssoData (decoded): '${destination}'`);
// sample : ZZ**DST:home
const realDst = this.ssoService.unHashLocalData(destination);
@ -78,8 +82,4 @@ export class SsoScene implements OnInit {
this.userService.removeSession();
}
}
}

View File

@ -9,7 +9,6 @@ import { HttpWrapperService } from 'common/service/http-wrapper';
import { isNullOrUndefined } from 'common/utils';
import { DataInterface } from 'common/utils/dataInterface';
@Injectable()
export class BddService {
private bdd = {};
@ -27,13 +26,14 @@ export class BddService {
self.get(name)
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.add(response2);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -45,13 +45,14 @@ export class BddService {
self.get(name)
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.set(id, response2);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -61,7 +62,8 @@ export class BddService {
self.get(name)
.then((response: DataInterface) => {
response.set(id, data);
}).catch((response) => {
})
.catch(response => {
// nothing to do ...
});
}
@ -72,13 +74,14 @@ export class BddService {
self.get(name)
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.delete(id);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -112,29 +115,36 @@ export class BddService {
// brut force update of the BDD : TODO optimise it later ...
//console.log(`Update BDD (${ name })`);
self.http.getSpecific(name)
.then((response) => {
self.http
.getSpecific(name)
.then(response => {
//console.log(`end download DB: ==> ${ name } ${ response.length}`);
self.bdd[name] = new DataInterface(name, response);
localStorage.setItem(self.baseLocalStorageName + name, JSON.stringify(self.bdd[name].bdd));
}).catch((response) => {
})
.catch(response => {
console.log(`[E] ${self.constructor.name}: cant not get data from remote server: ${name}`);
});
} else {
//console.log(`Download BDD (${ name })`);
return new Promise((resolve, reject) => {
self.http.getSpecific(name)
.then((response) => {
self.http
.getSpecific(name)
.then(response => {
//console.log(`end download DB: ==> ${ name } ${ response.length}`);// + " " + JSON.stringify(response).length);
self.bdd[name] = new DataInterface(name, response);
if (self.useLocalStorage === true) {
localStorage.setItem(self.baseLocalStorageName + name, JSON.stringify(self.bdd[name].bdd));
localStorage.setItem(
self.baseLocalStorageName + name,
JSON.stringify(self.bdd[name].bdd)
);
}
for (let iii = 0; iii < self.bddPomise[name].length; iii++) {
self.bddPomise[name][iii].resolve(self.bdd[name]);
}
resolve(self.bdd[name]);
}).catch((response) => {
})
.catch(response => {
console.log(`[E] ${self.constructor.name}: can not get data from remote server: ${name}`);
for (let iii = 0; iii < self.bddPomise[name].length; iii++) {
self.bddPomise[name][iii].reject(response);
@ -153,4 +163,3 @@ export class BddService {
});
}
}

View File

@ -8,10 +8,7 @@
@Injectable()
export class CookiesService {
constructor() {
}
constructor() {}
set(cname: string, cvalue: string, exdays: number): void {
if (this.get(cname) !== '') {
@ -43,5 +40,3 @@
return '';
}
}

View File

@ -13,19 +13,19 @@ import { SessionService } from './session';
import { isArrayOfs, isBoolean, isNullOrUndefined, isNumber, isString } from 'common/utils';
export enum HTTPRequestModel {
POST = "POST",
GET = "GET",
PUT = "PUT",
DELETE = "DELETE",
PATCH = "PATCH",
POST = 'POST',
GET = 'GET',
PUT = 'PUT',
DELETE = 'DELETE',
PATCH = 'PATCH',
}
export enum HTTPMimeType {
ALL = "*/*",
JSON = "application/json",
OCTET_STREAM = "application/octet-stream",
IMAGE = "image/*",
IMAGE_JPEG = "image/jpeg",
IMAGE_PNG = "image/png",
ALL = '*/*',
JSON = 'application/json',
OCTET_STREAM = 'application/octet-stream',
IMAGE = 'image/*',
IMAGE_JPEG = 'image/jpeg',
IMAGE_PNG = 'image/png',
}
export type UrlPath = string | boolean | number | (string | boolean | number)[];
@ -46,8 +46,8 @@ export interface HTTPRequest {
}
export interface ModelResponseHttp {
status: number,
data: any,
status: number;
data: any;
}
/**
@ -56,10 +56,7 @@ export interface ModelResponseHttp {
@Injectable()
export class HttpWrapperService {
private displayReturn: boolean = false;
constructor(private http: HttpClient,
private session: SessionService) {
}
constructor(private http: HttpClient, private session: SessionService) { }
addTokenIfNeeded(headerOption: any): any {
const token = this.session.getToken();
@ -72,26 +69,26 @@ export class HttpWrapperService {
}
request(properties: HTTPRequest): Promise<Response> {
//uriRest:string, headerOption:any, params:any): Promise<{status:number, data:any}> {
//console.log(`-------------------------------------------------------\nHTTP-wrapper GET '${ properties.endPoint }'\n\t\tparams=${ JSON.stringify(properties, null, 2)}`);
let connectionAdresse = this.createRESTCall2({
let connectionAddresses = this.createRESTCall2({
server: properties.server,
api: properties.endPoint,
inputOptions: properties.params,
});
let headers: any = {
'Accept': properties.accept,
Accept: properties.accept,
//'Content-Type': properties.contentType,
}
};
if (properties.authorization !== undefined && properties.authorization !== null) {
headers['Authorization'] = properties.authorization;
}
if (properties.requestType !== HTTPRequestModel.GET) {
headers['Content-Type'] = properties.contentType;
}
//console.log(`disble tocken : ${JSON.stringify(properties)} properties.disableTocken=${properties.disableTocken}`);
if (properties.disableTocken === undefined || properties.disableTocken === null || properties.disableTocken === false) {
if (
properties.disableTocken === undefined ||
properties.disableTocken === null ||
properties.disableTocken === false
) {
headers = this.addTokenIfNeeded(headers);
}
//console.log(`header: ${JSON.stringify(headers)}`);
@ -99,44 +96,56 @@ export class HttpWrapperService {
if (properties.contentType === HTTPMimeType.JSON) {
body = JSON.stringify(properties.body);
}
const result = fetch(connectionAdresse, {
console.log(`Call ${connectionAddresses}`)
const result = fetch(connectionAddresses, {
method: properties.requestType,
headers,
body
})
body,
});
return result;
};
}
requestJson(properties: HTTPRequest): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties).then((response: Response) => {
this.request(properties)
.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
response
.json()
.then((value: any) => {
//console.log(`RECEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
}).catch((reason:any)=> {
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`)
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 999, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`wring correct status: ${response.status}`)
console.error(`wring correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.catch((error: any) => {
reject({
time: Date(),
status: 999,
error: error,
statusMessage: "Fetch error",
message: "http-wrapper.ts detect an error in the fetch request"
});
});
};
});
}
requestImage(properties: HTTPRequest): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties).then((response: Response) => {
this.request(properties)
.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get('Content-Type');
//console.log(`REICEIVE ==> ${response.status}`);
@ -152,24 +161,39 @@ export class HttpWrapperService {
}
*/
} else {
console.error(`wring correct status: ${response.status}`)
console.error(`wring correct status: ${response.status}`);
resolve({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.catch((error: any) => {
reject({
time: Date(),
status: 999,
error: error,
statusMessage: "Fetch image error",
message: "http-wrapper.ts detect an error in the fetch request"
});
});
});
}
createRESTCall2({ api, server, inputOptions, addURLToken }: { server?: string; api: UrlPath; inputOptions?: object; addURLToken?:boolean }) {
createRESTCall2({
api,
server,
inputOptions,
addURLToken,
}: {
server?: string;
api: UrlPath;
inputOptions?: object;
addURLToken?: boolean;
}) {
if (isNullOrUndefined(server)) {
server = environment.defaultServer;
}
const basePage = environment.server[server];
let addressServerRest = basePage;
if (!basePage.endsWith("/")) {
if (!basePage.endsWith('/')) {
addressServerRest = `${basePage}/`;
}
let options = inputOptions;
@ -180,7 +204,7 @@ export class HttpWrapperService {
if (isArrayOfs(api, isString, isNumber, isBoolean)) {
for (let iii = 0; iii < api.length; iii++) {
let elem = api[iii];
if (out.endsWith("/")) {
if (out.endsWith('/')) {
out += elem;
} else {
out += `/${elem}`;
@ -200,7 +224,7 @@ export class HttpWrapperService {
}
out = out + keys[iii];
if (options[keys[iii]] != null) {
out = out + "=" + options[keys[iii]];
out = out + '=' + options[keys[iii]];
}
}
//console.log(`try to get session : ${this.session.getToken()}`);
@ -242,20 +266,20 @@ export class HttpWrapperService {
post(uriRest: string, headerOption: any, data: any, progress: ProgressCallback = null) {
//console.log(`-------------------------------------------------------\nHTTP-wrapper POST '${ uriRest }'\n\t\theaderOption=${ JSON.stringify(headerOption, null, 2)}\n\t\tdata=${ JSON.stringify(data, null, 2)}`);
this.addTokenIfNeeded(headerOption);
let connectionAdresse = this.createRESTCall(uriRest, {});
let connectionAddresses = this.createRESTCall(uriRest, {});
return new Promise((resolve, reject) => {
if (this.displayReturn === true) {
console.log(`call POST ${ connectionAdresse } data=${ JSON.stringify(data, null, 2)}`);
console.log(`call POST ${connectionAddresses} data=${JSON.stringify(data, null, 2)}`);
}
let request = this.http.post(connectionAdresse, data, {
let request = this.http.post(connectionAddresses, data, {
headers: new HttpHeaders(headerOption),
reportProgress: true,
observe: 'events'
observe: 'events',
});
let self = this;
request.subscribe((res: any) => {
request.subscribe(
(res: any) => {
if (self.displayReturn === true) {
console.log(`!! data ${JSON.stringify(res, null, 2)}`);
}
@ -287,13 +311,14 @@ export class HttpWrapperService {
console.log(`post : get unknown ... ${res.type}`);
}
},
(error) => {
error => {
if (self.displayReturn === true) {
console.log(`an error occured status: ${error.status}`);
console.log(`answer: ${JSON.stringify(error, null, 2)}`);
}
reject({ status: error.status, data: error.error });
});
}
);
});
}
// Deprecated ... old model stream
@ -307,21 +332,23 @@ export class HttpWrapperService {
// 'Content-Type': 'multipart/form-data',
}; // new Headers();
self.post(url, headers, multipart, progress)
.then((response: any) => {
self.post(url, headers, multipart, progress).then(
(response: any) => {
//console.log(`URL: ${ url }\nRespond(${ response.status }): ${ JSON.stringify(response.data, null, 2)}`);
if (response.status >= 200 && response.status <= 299) {
resolve(response.data.body);
return;
}
reject('An error occured');
}, (response: any) => {
},
(response: any) => {
if (typeof response.data === 'undefined') {
reject('return ERROR undefined');
} else {
reject('return ERROR ...'); // + JSON.stringify(response, null, 2));
}
});
}
);
});
}
@ -333,21 +360,23 @@ export class HttpWrapperService {
requestType: HTTPRequestModel.GET,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
})
.then((response: ModelResponseHttp) => {
}).then(
(response: ModelResponseHttp) => {
//console.log("URL: " + url + "\nRespond(" + response.status + "): " + JSON.stringify(response.data, null, 2));
if (response.status === 200) {
resolve(response.data);
return;
}
reject('An error occured');
}, (response: ModelResponseHttp) => {
},
(response: ModelResponseHttp) => {
if (isNullOrUndefined(response.data)) {
reject('return ERROR undefined');
} else {
reject(`return ERROR ${JSON.stringify(response.data, null, 2)}`);
}
});
}
);
});
}
@ -360,25 +389,30 @@ export class HttpWrapperService {
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: Response) => {
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
}).catch((reason:any)=> {
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`)
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`wrong correct status: ${response.status}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});
@ -391,25 +425,30 @@ export class HttpWrapperService {
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: Response) => {
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
}).catch((reason:any)=> {
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`)
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`wrong correct status: ${response.status}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});
@ -421,25 +460,30 @@ export class HttpWrapperService {
requestType: HTTPRequestModel.DELETE,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
}).then((response: Response) => {
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
}).catch((reason:any)=> {
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`)
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`wrong correct status: ${response.status}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});

View File

@ -1,11 +1,18 @@
import { BddService } from "./bdd";
import { CookiesService } from "./cookies";
import { HttpWrapperService, ModelResponseHttp, HTTPRequest, HTTPMimeType, HTTPRequestModel } from "./http-wrapper";
import { StorageService } from "./local-storage";
import { PopInService } from "./popin";
import { OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome, SessionService } from "./session";
import { SSOService } from "./sso";
import { UserService } from "./user";
import { BddService } from './bdd';
import { CookiesService } from './cookies';
import { HttpWrapperService, ModelResponseHttp, HTTPRequest, HTTPMimeType, HTTPRequestModel } from './http-wrapper';
import { StorageService } from './local-storage';
import { NotificationService } from './notification';
import { PopInService } from './popin';
import {
OnlyAdminGuard,
OnlyUnregisteredGuardHome,
OnlyUsersGuard,
OnlyUsersGuardHome,
SessionService,
} from './session';
import { SSOService } from './sso';
import { UserService } from './user';
export {
BddService,
@ -24,6 +31,5 @@ export {
OnlyUsersGuardHome,
OnlyUnregisteredGuardHome,
OnlyAdminGuard,
NotificationService,
};

View File

@ -11,9 +11,7 @@ import { environment } from 'environments/environment';
export class StorageService {
private baseLocalStorageName = environment.applName + '_';
constructor() {
}
constructor() {}
set(cname: string, cvalue: string): void {
//console.debug(`storage set: ${cname} : ${cvalue}`);
@ -50,5 +48,3 @@ import { environment } from 'environments/environment';
return data;
}
}

View File

@ -0,0 +1,25 @@
/** @file
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
@Injectable()
export class NotificationService {
constructor() {
console.log('Start Notification Service');
}
errorRaw(data: any) {
console.error(`get notification error: ${data}`)
}
warningRaw(data: any) {
console.info(`get notification warning: ${data}`)
}
infoRaw(data: any) {
console.info(`get notification info: ${data}`)
}
}

View File

@ -30,16 +30,17 @@ export class PopInService {
}
open(_id: string) {
// console.log("Try to open pop-in: '" + _id + "'");
console.log("Try to open pop-in: '" + _id + "'");
// open popin specified by id
for (let iii = 0; iii < this.popins.length; iii++) {
console.log(` check: ${this.popins[iii].id}`);
if (this.popins[iii].id === _id) {
// console.log(" ==>find it ...");
console.log(" ==>find it ...");
this.popins[iii].open();
return;
}
}
// console.log(" ==> NOT found !!!!!");
console.log(" ==> NOT found !!!!!");
}
close(_id: string) {

View File

@ -6,90 +6,97 @@
import { Injectable, Output, EventEmitter } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { isNullOrUndefined } from 'common/utils';
import { environment } from 'environments/environment';
export enum UserRoles222 {
admin = 10000,
user = 1,
guest = 10
admin = 'admin',
user = 'user',
guest = 'guest',
}
@Injectable()
export class SessionService {
private tokenJwt = null;
public sessionId = null;
public userLogin = null;
public userAdmin = null;
public userEMail = null;
public userAvatar = null;
public userId = null;
public right: any = {};
@Output() change: EventEmitter<boolean> = new EventEmitter();
constructor() {
}
constructor() { }
/**
* @brief Create a new session.
*
* @param sessionId -
* @param userId -
* @param userLogin -
* @param userEMail -
* @param userAdmin -
* @param userAvatar -
* @param tokenJwt -
*/
create({ sessionId, userId, userLogin, userEMail, userAdmin, userAvatar, tokenJwt }: {
sessionId;
create({
userId,
userLogin,
tokenJwt,
}: {
userId: string;
userLogin: string;
userEMail: string;
userAdmin: boolean;
userBlocked: boolean;
userRemoved: boolean;
userAvatar: string;
tokenJwt: string;
}) {
console.log(`Session Create: userId=${userId} userLogin=${userLogin} userEMail=${userEMail} userAdmin=${userAdmin} userAvatar=${userAvatar} sessionId = ${sessionId} tokenJwt = ${tokenJwt}`);
console.log(
`Session Create: userId=${userId} userLogin=${userLogin} tokenJwt = ${tokenJwt}`
);
this.tokenJwt = tokenJwt;
this.sessionId = sessionId;
this.userId = userId;
this.userLogin = userLogin;
this.userAdmin = userAdmin;
this.userEMail = userEMail;
this.userAvatar = userAvatar;
this.right = this.parseToken(tokenJwt);
console.log(`Retrieve right: ${JSON.stringify(this.right, null, 4)}`);
this.change.emit(true);
}
b64_to_utf8(str: string): string {
return decodeURIComponent(window.atob(str));
}
parseToken(token: string): any {
const cut = token.split('.');
const decoded = this.b64_to_utf8(cut[1]);
const jsonModel = JSON.parse(decoded);
if (isNullOrUndefined(jsonModel.right)) {
return {};
}
if (isNullOrUndefined(jsonModel.right[environment.applName])) {
return {};
}
return jsonModel.right[environment.applName];
}
/**
* @brief destroy the current session.
*/
destroy() {
console.log('Session REMOVE');
let last = this.sessionId;
this.sessionId = null;
this.tokenJwt = undefined;
this.userId = null;
this.userLogin = null;
this.userAdmin = null;
this.userEMail = null;
this.userAvatar = null;
this.right = {};
this.change.emit(false);
}
getToken(): string | undefined {
return this.tokenJwt;
}
islogged() {
return this.sessionId !== null;
return this.userId !== null;
}
hasRight(type) {
hasRight(type: UserRoles222): boolean {
if (type === UserRoles222.admin) {
// sometime needed...
return this.userAdmin;
if (isNullOrUndefined(this.right.ADMIN)) {
return false;
}
return this.right.ADMIN;
}
if (type === UserRoles222.user) {
// is connected ==> is user
return this.sessionId !== null;
if (isNullOrUndefined(this.right.USER)) {
return false;
}
return this.right.USER;
}
if (type === UserRoles222.guest) {
// all the other ... maybe unneeded
@ -116,11 +123,10 @@ export class SessionService {
@Injectable()
export class OnlyUsersGuard implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
console.log("OnlyLoggedInUsers");
console.log('OnlyLoggedInUsers');
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
return true;
} else {
@ -132,8 +138,7 @@ export class OnlyUsersGuard implements CanActivate {
@Injectable()
export class OnlyUsersGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
@ -146,8 +151,7 @@ export class OnlyUsersGuardHome implements CanActivate {
}
@Injectable()
export class OnlyUnregisteredGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (!this.sessionService.islogged()) {
@ -161,8 +165,7 @@ export class OnlyUnregisteredGuardHome implements CanActivate {
@Injectable()
export class OnlyAdminGuard implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user)) {

View File

@ -13,14 +13,12 @@ import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp }
export class SSOService {
signUpEnable: boolean = undefined;
constructor(
private http: HttpWrapperService,
) {
constructor(private http: HttpWrapperService) {
console.log('Start SSOService');
}
utf8_to_b64(str: string): string {
// remove unneeded "=" padding
return window.btoa(encodeURIComponent( str )).replace("=", "");
return window.btoa(encodeURIComponent(str)).replace('=', '');
}
b64_to_utf8(str: string): string {
@ -30,14 +28,40 @@ export class SSOService {
* Request SSO connection
*/
hashLocalData(data?: string): string {
if (!isNullOrUndefined(data) && !isInArray(data, ["", "null", "NULL", "undefined", "---", "unregistered", "unregistered/", "forbidden", "forbidden/"])) {
if (
!isNullOrUndefined(data) &&
!isInArray(data, [
'',
'null',
'NULL',
'undefined',
'---',
'unregistered',
'unregistered/',
'forbidden',
'forbidden/',
])
) {
return this.utf8_to_b64(data);
}
let pathName = getApplicationLocation();
if (isInArray(pathName, ["sso", "/sso", "/sso/"])) {
const pathName = getApplicationLocation();
if (isInArray(pathName, ['sso', '/sso', '/sso/'])) {
return this.utf8_to_b64('home');
}
if (!isNullOrUndefined(pathName) && !isInArray(pathName, ["", "null", "NULL", "undefined", "---", "unregistered", "unregistered/", "forbidden", "forbidden/"])) {
if (
!isNullOrUndefined(pathName) &&
!isInArray(pathName, [
'',
'null',
'NULL',
'undefined',
'---',
'unregistered',
'unregistered/',
'forbidden',
'forbidden/',
])
) {
return this.utf8_to_b64(pathName);
}
return this.utf8_to_b64('home');
@ -46,17 +70,22 @@ export class SSOService {
* Request SSO connection
*/
unHashLocalData(data: string): string | undefined {
if (isNullOrUndefined(data) || isInArray(data, ["", "null", "NULL", "undefined", "---"])) {
if (isNullOrUndefined(data) || isInArray(data, ['', 'null', 'NULL', 'undefined', '---'])) {
return undefined;
}
try {
return this.b64_to_utf8(data);
}
catch (ex) {
} catch (ex) {
console.error(`Can not convert the data: ${data}`);
}
return undefined;
}
/**
* Request Open SSO Global website
*/
requestOpenSite(): void {
window.location.href = environment.ssoSite;
}
/**
* Request SSO connection
*/
@ -83,24 +112,24 @@ export class SSOService {
let self = this;
return new Promise((resolve, reject) => {
if (isNullOrUndefined(self.signUpEnable)) {
this.http.requestJson({
this.http
.requestJson({
server: 'karso',
endPoint: 'system_config/is_sign_up_availlable',
requestType: HTTPRequestModel.GET,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
}).then((response: ModelResponseHttp) =>{
})
.then((response: ModelResponseHttp) => {
self.signUpEnable = response.data.signup;
resolve(self.signUpEnable);
}).catch((error:any) => {
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
return;
}
resolve(self.signUpEnable);
});
}
}

View File

@ -6,7 +6,6 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { environment } from 'environments/environment';
import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp } from './http-wrapper';
@ -15,21 +14,21 @@ import { SessionService } from './session';
import { SSOService } from './sso';
import { getApplicationLocation, isNullOrUndefined, sha512 } from 'common/utils';
/*
interface MessageLogIn {
login: string;
method: string;
time: number;
password: string;
}
interface MessageAnswer_USER_CONNECT {
sessionId: string,
login: string,
eMail: string,
role: string,
avatar: string
sessionId: string;
login: string;
eMail: string;
role: string;
avatar: string;
}
*/
@Injectable()
export class UserService {
// 0: Not hide password; 1 hide password;
@ -42,7 +41,8 @@ export class UserService {
private storageService: StorageService,
private http: HttpWrapperService,
private sessionService: SessionService,
private ssoService: SSOService) {
private ssoService: SSOService
) {
console.log('Start UserService');
}
@ -51,8 +51,7 @@ export class UserService {
*/
logOut(): void {
this.removeSession();
this.ssoService.requestSignOut("home");
this.ssoService.requestSignOut('home');
}
removeSession(): void {
this.storageService.remove(this.cookiesRememberMe);
@ -74,34 +73,44 @@ export class UserService {
const tokenData = decodeURIComponent(window.atob(elems[1]));
// console.error(`Retreive local token: \nheader=${tokenHeader} \ndata=${tokenData}`);
const parsedData = JSON.parse(tokenData);
console.debug(`Retreive token exp data=${new Date(parsedData.exp*1000).toISOString()} < ${new Date().toISOString()}`);
console.debug(
`Retreive token exp data=${new Date(parsedData.exp * 1000).toISOString()} < ${new Date().toISOString()}`
);
const expireIn = new Date(parsedData.exp * 1000);
const nowTime = new Date();
// TODO: set a marging of 2 hours...
return expireIn > nowTime;
}
getRememberMe(): boolean {
return this.storageService.get(this.cookiesRememberMe) === 'true';
}
/**
* Check if the system can be connected
*/
checkAutoConnect(): Promise<void> {
let locationOrigin = getApplicationLocation();
let self = this;
const self = this;
return new Promise<void>((resolve, reject) => {
// Need to use the windows global route to prevent the log in cycle ...
// And in the mlain application position, the route does not have curently root the page
let pathName = window.location.pathname;
// console.log("start Path-name: '" + pathName + "'");
// console.log("check with: '" + environment.applName + "/sso/" + "'");
if (pathName.startsWith("/sso/") || pathName.startsWith(environment.applName + "/sso/")) {
console.log(" ==> SSo section");
if (pathName.startsWith('/sso/') || pathName.startsWith(environment.applName + '/sso/')) {
console.log(' ==> SSo section');
reject();
return;
}
console.log(" ==> Check if need reconnect?");
let rememberMe = self.storageService.get(self.cookiesRememberMe)==="true";
console.log(' ==> Check if need reconnect?');
let rememberMe = self.getRememberMe();
// TODO: in case of jest reload ==> no need to manage the SSO ==> just keep the token ... it in enought...
let token = null;
if (isNullOrUndefined(environment.tokenStoredInPermanentStorage) || environment.tokenStoredInPermanentStorage !== true) {
if (
isNullOrUndefined(environment.tokenStoredInPermanentStorage) ||
environment.tokenStoredInPermanentStorage !== true
) {
token = self.storageService.getSession(self.cookiesToken);
} else {
token = self.storageService.get(self.cookiesToken);
@ -111,11 +120,13 @@ export class UserService {
// remove in case of fail !!!
this.storageService.removeSession(this.cookiesToken);
this.storageService.remove(this.cookiesToken);
self.startSession(token, rememberMe).then(() => {
self.startSession(token, rememberMe)
.then(() => {
self.router.navigateByUrl(locationOrigin);
console.log(`update global URL = ${locationOrigin}`);
resolve();
}).catch(() => {
})
.catch(() => {
// jump in the sign-in page (automatically of request remember-me)
if (rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
@ -143,52 +154,58 @@ export class UserService {
}
startSession(token: string, rememberMe: boolean): Promise<string> {
let self = this;
const self = this;
return new Promise((resolve, reject) => {
self.retreiveMe(token).then(
(value2: boolean) => {
self.retreiveMe(token)
.then((value2: boolean) => {
if (rememberMe === true) {
self.storageService.set(self.cookiesRememberMe, rememberMe?"true":"false");
self.storageService.set(self.cookiesRememberMe, rememberMe ? 'true' : 'false');
}
if (isNullOrUndefined(environment.tokenStoredInPermanentStorage) || environment.tokenStoredInPermanentStorage !== true) {
if (
isNullOrUndefined(environment.tokenStoredInPermanentStorage) ||
environment.tokenStoredInPermanentStorage !== true
) {
self.storageService.setSession(self.cookiesToken, token);
} else {
self.storageService.set(self.cookiesToken, token);
}
resolve(self.sessionService.getLogin());
}).catch(() => {
})
.catch(() => {
reject('sdfsdfsdf');
});
});
}
retreiveMe(token: string): Promise<boolean> {
console.log(`AuthService.loginWithToken ... '${token}'`);
let self = this;
const self = this;
return new Promise((resolve, reject) => {
this.http.requestJson({
this.http
.requestJson({
// server: 'karso',
endPoint: 'users/me',
requestType: HTTPRequestModel.GET,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
authorization: `Yota ${token}`, // special case, the token is set after this request...
}).then((response: ModelResponseHttp) =>{
})
.then((response: ModelResponseHttp) => {
// TODO: check type ...
console.log(`loginWithToken : get some data to check: ${JSON.stringify(response.data)}`)
self.sessionService.create(
{
sessionId: response.data.sessionId,
console.log(`loginWithToken : get some data to check: ${JSON.stringify(response.data)}`);
self.sessionService.create({
//sessionId: response.data.sessionId,
userId: response.data.id,
userLogin: response.data.login,
userEMail: response.data.email,
userAdmin: response.data.admin,
userBlocked: response.data.blocked,
userRemoved: response.data.removed,
userAvatar: response.data.avatar,
//userEMail: response.data.email,
//userAdmin: response.data.admin,
//userBlocked: response.data.blocked,
//userRemoved: response.data.removed,
//userAvatar: response.data.avatar,
tokenJwt: token,
});
resolve(true);
}).catch((error:any) => {
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
@ -202,7 +219,7 @@ export class UserService {
method: 'v?',
login: login,
email: email,
password: password
password: password,
};
console.log(`call users data=${JSON.stringify(data, null, 2)}`);
@ -211,18 +228,21 @@ export class UserService {
}
return new Promise((resolve, reject) => {
this.http.requestJson({
this.http
.requestJson({
server: 'karso',
endPoint: 'users',
requestType: HTTPRequestModel.POST,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: ModelResponseHttp) =>{
})
.then((response: ModelResponseHttp) => {
// TODO: check type ...
console.log(`createSha : get some data to check: ${JSON.stringify(response.data)}`)
console.log(`createSha : get some data to check: ${JSON.stringify(response.data)}`);
resolve(response.data);
}).catch((error:any) => {
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
@ -244,4 +264,3 @@ export class UserService {
return false;
}
}

View File

@ -1,4 +1,4 @@
import { environment } from "environments/environment";
import { environment } from 'environments/environment';
export function getApplicationLocation(): string {
let pathName = location.pathname;

View File

@ -4,8 +4,8 @@
* @license PROPRIETARY (see license file)
*/
import { NodeData } from "../model";
import { isArray, isNullOrUndefined } from "./validator";
import { NodeData } from '../model';
import { isArray, isNullOrUndefined } from './validator';
export enum TypeCheck {
CONTAINS = 'C',
@ -51,10 +51,7 @@ export class DataInterface {
}
return out;
}
constructor(
private name: string,
private bdd: NodeData[] ) {
}
constructor(private name: string, private bdd: NodeData[]) {}
public getTableIndex(id: number) {
for (let iii = 0; iii < this.bdd.length; iii++) {
@ -173,7 +170,10 @@ export class DataInterface {
}
return value === listValues;
}
public static containsOneIn(value: number|string|boolean|number[]|string[], listValues:number|string|boolean|number[]|string[]): boolean {
public static containsOneIn(
value: number | string | boolean | number[] | string[],
listValues: number | string | boolean | number[] | string[]
): boolean {
if (isArray(value)) {
for (let iii = 0; iii < value.length; iii++) {
if (this.existIn(value[iii], listValues) === true) {
@ -192,10 +192,10 @@ export class DataInterface {
if (select.length === 0) {
find = false;
}
// console.log("Check : " + JSON.stringify(_values[iii_elem], null, 2));
//console.log("Check : " + JSON.stringify(values[iiiElem], null, 2));
for (let iiiSelect = 0; iiiSelect < select.length; iiiSelect++) {
let control = select[iiiSelect];
let valueElement = values[iiiElem][control.key]
let valueElement = values[iiiElem][control.key];
//console.log(" valueElement : " + JSON.stringify(valueElement, null, 2));
if (isArray(control.value)) {
if (control.check === TypeCheck.CONTAINS) {
@ -328,4 +328,3 @@ export class DataInterface {
return out;
}
}

View File

@ -1,9 +1,25 @@
import { getApplicationLocation } from "./applPath";
import { DataInterface, TypeCheck } from "./dataInterface";
import { sha512 } from "./sha512";
import { isArray, isArrayOf, isBoolean, isNull, isNullOrUndefined, isNumber, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString, isUndefined, isArrayOfs, isInArray, isStringNullOrUndefined } from "./validator";
import { getApplicationLocation } from './applPath';
import { DataInterface, TypeCheck } from './dataInterface';
import { sha512 } from './sha512';
import {
isArray,
isArrayOf,
isBoolean,
isNull,
isNullOrUndefined,
isNumber,
isNumberFinite,
isObject,
isOptionalOf,
isOptionalArrayOf,
isString,
isUndefined,
isArrayOfs,
isInArray,
isStringNullOrUndefined,
isNumeric,
} from './validator';
import { checkEmailValidity, checkLoginValidity, checkPasswordValidity, createLoginState, createPasswordState, getLoginType } from './validatorPasswordEmail';
export {
isNumber,
@ -25,5 +41,11 @@ export {
TypeCheck,
getApplicationLocation,
sha512,
}
createPasswordState,
checkEmailValidity,
checkPasswordValidity,
checkLoginValidity,
getLoginType,
createLoginState,
isNumeric,
};

View File

@ -1,7 +1,3 @@
export function isMobileAgent() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}

View File

@ -8,51 +8,99 @@ export function sha512(str) {
this.lowOrder = lsint_32;
}
let H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b),
new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1),
new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f),
new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)];
let H = [
new int64(0x6a09e667, 0xf3bcc908),
new int64(0xbb67ae85, 0x84caa73b),
new int64(0x3c6ef372, 0xfe94f82b),
new int64(0xa54ff53a, 0x5f1d36f1),
new int64(0x510e527f, 0xade682d1),
new int64(0x9b05688c, 0x2b3e6c1f),
new int64(0x1f83d9ab, 0xfb41bd6b),
new int64(0x5be0cd19, 0x137e2179),
];
let K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd),
new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc),
new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019),
new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118),
new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe),
new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2),
new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1),
new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694),
new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3),
new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65),
new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5),
new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210),
new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4),
new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725),
new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70),
new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df),
new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8),
new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b),
new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001),
new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30),
new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910),
new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53),
new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8),
new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb),
new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3),
new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec),
new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9),
new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b),
new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207),
new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178),
new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6),
new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b),
new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c),
new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a),
new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
let K = [
new int64(0x428a2f98, 0xd728ae22),
new int64(0x71374491, 0x23ef65cd),
new int64(0xb5c0fbcf, 0xec4d3b2f),
new int64(0xe9b5dba5, 0x8189dbbc),
new int64(0x3956c25b, 0xf348b538),
new int64(0x59f111f1, 0xb605d019),
new int64(0x923f82a4, 0xaf194f9b),
new int64(0xab1c5ed5, 0xda6d8118),
new int64(0xd807aa98, 0xa3030242),
new int64(0x12835b01, 0x45706fbe),
new int64(0x243185be, 0x4ee4b28c),
new int64(0x550c7dc3, 0xd5ffb4e2),
new int64(0x72be5d74, 0xf27b896f),
new int64(0x80deb1fe, 0x3b1696b1),
new int64(0x9bdc06a7, 0x25c71235),
new int64(0xc19bf174, 0xcf692694),
new int64(0xe49b69c1, 0x9ef14ad2),
new int64(0xefbe4786, 0x384f25e3),
new int64(0x0fc19dc6, 0x8b8cd5b5),
new int64(0x240ca1cc, 0x77ac9c65),
new int64(0x2de92c6f, 0x592b0275),
new int64(0x4a7484aa, 0x6ea6e483),
new int64(0x5cb0a9dc, 0xbd41fbd4),
new int64(0x76f988da, 0x831153b5),
new int64(0x983e5152, 0xee66dfab),
new int64(0xa831c66d, 0x2db43210),
new int64(0xb00327c8, 0x98fb213f),
new int64(0xbf597fc7, 0xbeef0ee4),
new int64(0xc6e00bf3, 0x3da88fc2),
new int64(0xd5a79147, 0x930aa725),
new int64(0x06ca6351, 0xe003826f),
new int64(0x14292967, 0x0a0e6e70),
new int64(0x27b70a85, 0x46d22ffc),
new int64(0x2e1b2138, 0x5c26c926),
new int64(0x4d2c6dfc, 0x5ac42aed),
new int64(0x53380d13, 0x9d95b3df),
new int64(0x650a7354, 0x8baf63de),
new int64(0x766a0abb, 0x3c77b2a8),
new int64(0x81c2c92e, 0x47edaee6),
new int64(0x92722c85, 0x1482353b),
new int64(0xa2bfe8a1, 0x4cf10364),
new int64(0xa81a664b, 0xbc423001),
new int64(0xc24b8b70, 0xd0f89791),
new int64(0xc76c51a3, 0x0654be30),
new int64(0xd192e819, 0xd6ef5218),
new int64(0xd6990624, 0x5565a910),
new int64(0xf40e3585, 0x5771202a),
new int64(0x106aa070, 0x32bbd1b8),
new int64(0x19a4c116, 0xb8d2d0c8),
new int64(0x1e376c08, 0x5141ab53),
new int64(0x2748774c, 0xdf8eeb99),
new int64(0x34b0bcb5, 0xe19b48a8),
new int64(0x391c0cb3, 0xc5c95a63),
new int64(0x4ed8aa4a, 0xe3418acb),
new int64(0x5b9cca4f, 0x7763e373),
new int64(0x682e6ff3, 0xd6b2b8a3),
new int64(0x748f82ee, 0x5defb2fc),
new int64(0x78a5636f, 0x43172f60),
new int64(0x84c87814, 0xa1f0ab72),
new int64(0x8cc70208, 0x1a6439ec),
new int64(0x90befffa, 0x23631e28),
new int64(0xa4506ceb, 0xde82bde9),
new int64(0xbef9a3f7, 0xb2c67915),
new int64(0xc67178f2, 0xe372532b),
new int64(0xca273ece, 0xea26619c),
new int64(0xd186b8c7, 0x21c0c207),
new int64(0xeada7dd6, 0xcde0eb1e),
new int64(0xf57d4f7f, 0xee6ed178),
new int64(0x06f067aa, 0x72176fba),
new int64(0x0a637dc5, 0xa2c898a6),
new int64(0x113f9804, 0xbef90dae),
new int64(0x1b710b35, 0x131c471b),
new int64(0x28db77f5, 0x23047d84),
new int64(0x32caab7b, 0x40c72493),
new int64(0x3c9ebe0a, 0x15c9bebc),
new int64(0x431d67c4, 0x9c100d4c),
new int64(0x4cc5d4be, 0xcb3e42b6),
new int64(0x597f299c, 0xfc657e2a),
new int64(0x5fcb6fab, 0x3ad6faec),
new int64(0x6c44198c, 0x4a475817),
];
let W = new Array(64);
let a, b, c, d, e, f, g, h, i, j;
@ -76,14 +124,14 @@ export function sha512(str) {
}
function binb2hex(binarray) {
let hex_tab = "0123456789abcdef";
let str = "";
let hex_tab = '0123456789abcdef';
let str = '';
let length = binarray.length * 4;
let srcByte;
for (let i = 0; i < length; i += 1) {
srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF);
str += hex_tab.charAt((srcByte >> 4) & 0xf) + hex_tab.charAt(srcByte & 0xf);
}
return str;
@ -92,13 +140,13 @@ export function sha512(str) {
function safe_add_2(x, y) {
let lsw, msw, lowOrder, highOrder;
lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
return new int64(highOrder, lowOrder);
}
@ -106,13 +154,18 @@ export function sha512(str) {
function safe_add_4(a, b, c, d) {
let lsw, msw, lowOrder, highOrder;
lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
lsw = (a.lowOrder & 0xffff) + (b.lowOrder & 0xffff) + (c.lowOrder & 0xffff) + (d.lowOrder & 0xffff);
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
lsw =
(a.highOrder & 0xffff) +
(b.highOrder & 0xffff) +
(c.highOrder & 0xffff) +
(d.highOrder & 0xffff) +
(msw >>> 16);
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
return new int64(highOrder, lowOrder);
}
@ -120,13 +173,36 @@ export function sha512(str) {
function safe_add_5(a, b, c, d, e) {
let lsw, msw, lowOrder, highOrder;
lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF);
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lsw =
(a.lowOrder & 0xffff) +
(b.lowOrder & 0xffff) +
(c.lowOrder & 0xffff) +
(d.lowOrder & 0xffff) +
(e.lowOrder & 0xffff);
msw =
(a.lowOrder >>> 16) +
(b.lowOrder >>> 16) +
(c.lowOrder >>> 16) +
(d.lowOrder >>> 16) +
(e.lowOrder >>> 16) +
(lsw >>> 16);
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16);
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lsw =
(a.highOrder & 0xffff) +
(b.highOrder & 0xffff) +
(c.highOrder & 0xffff) +
(d.highOrder & 0xffff) +
(e.highOrder & 0xffff) +
(msw >>> 16);
msw =
(a.highOrder >>> 16) +
(b.highOrder >>> 16) +
(c.highOrder >>> 16) +
(d.highOrder >>> 16) +
(e.highOrder >>> 16) +
(lsw >>> 16);
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
return new int64(highOrder, lowOrder);
}
@ -182,7 +258,9 @@ export function sha512(str) {
}
function gamma0(x) {
let rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
let rotr1 = rotr(x, 1),
rotr8 = rotr(x, 8),
shr7 = shr(x, 7);
return new int64(
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
@ -203,15 +281,9 @@ export function sha512(str) {
function shr(x, n) {
if (n <= 32) {
return new int64(
x.highOrder >>> n,
x.lowOrder >>> n | (x.highOrder << (32 - n))
);
return new int64(x.highOrder >>> n, (x.lowOrder >>> n) | (x.highOrder << (32 - n)));
} else {
return new int64(
0,
x.highOrder << (32 - n)
);
return new int64(0, x.highOrder << (32 - n));
}
}
@ -219,7 +291,7 @@ export function sha512(str) {
let strlen = str.length * charsize;
str = str2binb(str);
str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
str[strlen >> 5] |= 0x80 << (24 - (strlen % 32));
str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
for (let i = 0; i < str.length; i += 32) {

View File

@ -1,15 +1,19 @@
export function isNumeric(val: string): boolean {
return !isNaN(Number(val));
}
export function isNumber(data: any): data is number {
return typeof data === "number";
return typeof data === 'number';
}
export function isNumberFinite(data: any): data is number {
return isNumber(data) && isFinite(data);
}
export function isBoolean(data: any): data is boolean {
return typeof data === "boolean";
return typeof data === 'boolean';
}
export function isString(data: any): data is string {
return typeof data === "string";
return typeof data === 'string';
}
export function isArray(data: any): data is any[] {
return Array.isArray(data);
@ -24,12 +28,10 @@ export function isNullOrUndefined(data: any): data is undefined | null {
return data === undefined || data === null;
}
export function isStringNullOrUndefined(data: any): data is undefined | null {
return data === "undefined" || data === "null" || data === "";
return data === 'undefined' || data === 'null' || data === '';
}
export function isObject(data: any): data is any {
return !isNullOrUndefined(data)
&& typeof data === 'object'
&& !isArray(data);
return !isNullOrUndefined(data) && typeof data === 'object' && !isArray(data);
}
export function isInArray(data: any, listElment: any[]): boolean {
for (let iii = 0; iii < listElment.length; iii++) {
@ -40,7 +42,11 @@ export function isInArray(data: any, listElment: any[]): boolean {
return false;
}
export function isArrayOf<TYPE>(data: any, typeChecker: (subData: any) => subData is TYPE, length?: number): data is TYPE[] {
export function isArrayOf<TYPE>(
data: any,
typeChecker: (subData: any) => subData is TYPE,
length?: number
): data is TYPE[] {
if (!isArray(data)) {
return false;
}
@ -52,10 +58,12 @@ export function isArrayOf<TYPE>(data: any, typeChecker: (subData: any) => subDat
}
return true;
}
export function isArrayOfs<TYPE,TYPE2,TYPE3>(data: any,
export function isArrayOfs<TYPE, TYPE2, TYPE3>(
data: any,
typeChecker: (subData: any) => subData is TYPE,
typeChecker2?: (subData: any) => subData is TYPE2,
typeChecker3?: (subData: any) => subData is TYPE3): data is (TYPE|TYPE2|TYPE3)[] {
typeChecker3?: (subData: any) => subData is TYPE3
): data is (TYPE | TYPE2 | TYPE3)[] {
if (!isArray(data)) {
return false;
}
@ -75,11 +83,16 @@ export function isArrayOfs<TYPE,TYPE2,TYPE3>(data: any,
return true;
}
export function isOptionalOf<TYPE>(data: any, typeChecker: (subData: any) => subData is TYPE): data is TYPE | undefined {
export function isOptionalOf<TYPE>(
data: any,
typeChecker: (subData: any) => subData is TYPE
): data is TYPE | undefined {
return isUndefined(data) || typeChecker(data);
}
export function isOptionalArrayOf<TYPE>(data: any, typeChecker: (subData: any) => subData is TYPE): data is TYPE[] | undefined {
export function isOptionalArrayOf<TYPE>(
data: any,
typeChecker: (subData: any) => subData is TYPE
): data is TYPE[] | undefined {
return isUndefined(data) || isArrayOf(data, typeChecker);
}

View File

@ -0,0 +1,146 @@
import { isNullOrUndefined } from "./validator";
/**
* Test the specific regexp on a value
* @param value Value to test.
* @param expression Regexp epression to test on the value
* @returns true if the regexp is validate, false otherwise
*/
export function testRegExp(value: string, expression: string): boolean {
let regexCheck = new RegExp(expression);
if (regexCheck.test(value)) {
return true;
}
return false;
}
/**
* Check the value is well formated to be a login.
* @param value login value to check.
* @returns true if it is compatible with a login, false otherwise.
*/
export function checkLoginValidity(value: string): boolean {
return testRegExp(value, '^[a-zA-Z0-9_\\.-]+$');
}
/**
* Check the value is well formated to be an e-mail.
* @param value email value to check.
* @returns true if it is an email, false otherwise.
*/
export function checkEmailValidity(value: string): boolean {
return testRegExp(value, '^[a-zA-Z0-9_\\.@-]+@[a-zA-Z0-9_\\.-]+\\.[a-zA-Z]+$');
}
/**
* Check the value is well formated to be an Password.
* @param value password value to check.
* @returns true if it is compatible with a password, false otherwise.
*/
export function checkPasswordValidity(value: string): boolean {
return testRegExp(value, '^[a-zA-Z0-9_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>\\-£€]+$');
}
/**
* Check if the value contains one alphabetical lower case character
* @param value String value to check.
* @returns true if it contains one lower case character, false otherwise.
*/
export function check1LowerChar(value: string): boolean {
return testRegExp(value, '(.*[a-z].*)');
}
/**
* Check if the value contains one alphabetical upper case character
* @param value String value to check.
* @returns true if it contains one upper case character, false otherwise.
*/
export function check1UpperChar(value: string): boolean {
return testRegExp(value, '(.*[A-Z].*)');
}
/**
* Check if the value contains one numerical character
* @param value String value to check.
* @returns true if it contains minimum of one digit character, false otherwise.
*/
export function check1DigitChar(value: string): boolean {
return testRegExp(value, '(.*[0-9].*)');
}
/**
* Check if the value contains one special character
* @param value String value to check.
* @returns true if it contains minimum of one special character, false otherwise.
*/
export function check1SpecialChar(value: string): boolean {
return testRegExp(value, '(.*[_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>\\-£€].*)');
}
/**
* Creata a pasword state of a password. it return a readable string that explain why the password is wrong.
* if check minimum size, at lease one digit, one upper case, one lower case and one special character.
* @param value Pasword value to check.
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
*/
export function createPasswordState(value: string): boolean|string {
let ret = createPasswordStateSimple(value);
if (ret === true) {
if (check1LowerChar(value) === false) {
return 'Not valid: missing 1 lower case character [a-z]';
}
if (check1UpperChar(value) === false) {
return 'Not valid: missing 1 upper case character [A-Z]';
}
if (check1DigitChar(value) === false) {
return 'Not valid: missing 1 digit character [0-9]';
}
if (check1SpecialChar(value) === false) {
return 'Not valid: missing 1 special character: _-:;.,?!*+=}{([|)]% @&~#/\\<>';
}
}
return ret;
}/**
* Creata a pasword state of a password. it return a readable string that explain why the password is wrong.
* It does not check if the email have specific less one char, it is dangerous for login interface.
* @param value Pasword value to check.
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
*/
export function createPasswordStateSimple(value: string): boolean|string {
if (isNullOrUndefined(value) || value === '') {
return false;
}
if (value.length < 6) {
return 'Need 6 characters';
}
if (checkPasswordValidity(value) === false) {
return 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\\<>"';
}
return true;
}
/**
* Creata a login/email state. It return a readable string that explain why the login/email is wrong.
* if check minimum size, or not an email.
* @param value email/login value to check.
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
*/
export function createLoginState(value: string): boolean|string {
if (isNullOrUndefined(value) || value === '') {
return false;
}
if (value.length < 6) {
return 'Need 6 characters';
}
if (checkLoginValidity(value) === true) {
return true;
} else if (checkEmailValidity(value) === true) {
return true;
} else {
return 'Not valid: characters, numbers, "_-." and email format: you@example.com';
}
}
export function getLoginType(value: string): string {
if (isNullOrUndefined(value) || value.length <6 ) {
return 'Username/E-mail';
}
if (checkLoginValidity(value) === true) {
return 'Username';
} else if (checkEmailValidity(value) === true) {
return 'E-mail';
}
return 'Username/E-mail';
}

View File

@ -12,6 +12,7 @@ export const environment = {
karideo: `${location.origin}/karideo/api`,
karso: `${location.origin}/karso/api`,
},
ssoSite: `${location.origin}/karso/`,
ssoSignIn: `${location.origin}/karso/signin/karideo/`,
ssoSignUp: `${location.origin}/karso/signup/karideo/`,
ssoSignOut: `${location.origin}/karso/signout/karideo/`,

View File

@ -3,18 +3,21 @@
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.
const serverSSOAddress = 'http://atria-soft.org'
const environment_back_prod = {
production: false,
// URL of development API
applName: "karideo",
defaultServer: "karideo",
server: {
karideo: 'http://192.168.1.156/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karideo: `${serverSSOAddress}/karideo/api`,
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
@ -25,11 +28,12 @@ const environment_local = {
defaultServer: "karideo",
server: {
karideo: 'http://localhost:18080/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
@ -39,15 +43,16 @@ const environment_hybrid = {
applName: "karideo",
defaultServer: "karideo",
server: {
karideo: 'http://192.168.1.156/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karideo: `${serverSSOAddress}/karideo/api`,
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
export const environment = environment_back_prod;
export const environment = environment_local;