[FEAT] some corrections and update dependency
This commit is contained in:
parent
ad26736b80
commit
d3e05889a9
@ -15,10 +15,16 @@
|
|||||||
<arguments>
|
<arguments>
|
||||||
</arguments>
|
</arguments>
|
||||||
</buildCommand>
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>edu.umd.cs.findbugs.plugin.eclipse.findbugsNature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
<filteredResources>
|
<filteredResources>
|
||||||
<filter>
|
<filter>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>kangaroo-and-rabbit</groupId>
|
<groupId>kangaroo-and-rabbit</groupId>
|
||||||
<artifactId>archidata</artifactId>
|
<artifactId>archidata</artifactId>
|
||||||
<version>0.10.2</version>
|
<version>0.11.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
@ -40,13 +40,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>5.11.0-M1</version>
|
<version>5.11.0-M2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<version>5.11.0-M1</version>
|
<version>5.11.0-M2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -12,11 +12,7 @@ import org.kar.archidata.UpdateJwtPublicKey;
|
|||||||
import org.kar.archidata.api.DataResource;
|
import org.kar.archidata.api.DataResource;
|
||||||
import org.kar.archidata.backup.BackupEngine;
|
import org.kar.archidata.backup.BackupEngine;
|
||||||
import org.kar.archidata.backup.BackupEngine.StoreMode;
|
import org.kar.archidata.backup.BackupEngine.StoreMode;
|
||||||
import org.kar.archidata.catcher.ExceptionCatcher;
|
import org.kar.archidata.catcher.GenericCatcher;
|
||||||
import org.kar.archidata.catcher.FailException404API;
|
|
||||||
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.db.DBConfig;
|
||||||
import org.kar.archidata.filter.CORSFilter;
|
import org.kar.archidata.filter.CORSFilter;
|
||||||
import org.kar.archidata.filter.OptionFilter;
|
import org.kar.archidata.filter.OptionFilter;
|
||||||
@ -121,11 +117,7 @@ public class WebLauncher {
|
|||||||
// global authentication system
|
// global authentication system
|
||||||
rc.register(KarsoAuthenticationFilter.class);
|
rc.register(KarsoAuthenticationFilter.class);
|
||||||
// register exception catcher
|
// register exception catcher
|
||||||
rc.register(InputExceptionCatcher.class);
|
GenericCatcher.addAll(rc);
|
||||||
rc.register(SystemExceptionCatcher.class);
|
|
||||||
rc.register(FailExceptionCatcher.class);
|
|
||||||
rc.register(FailException404API.class);
|
|
||||||
rc.register(ExceptionCatcher.class);
|
|
||||||
// add default resource:
|
// add default resource:
|
||||||
rc.register(DataResource.class);
|
rc.register(DataResource.class);
|
||||||
rc.register(ApplicationResource.class);
|
rc.register(ApplicationResource.class);
|
||||||
|
@ -52,7 +52,7 @@ public class UserResource {
|
|||||||
private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class UserOut {
|
public static class UserOut {
|
||||||
public long id;
|
public long id;
|
||||||
public String login;
|
public String login;
|
||||||
|
|
||||||
@ -276,8 +276,9 @@ public class UserResource {
|
|||||||
"FAIL Authentiocate-wrong email/login '" + login + "')");
|
"FAIL Authentiocate-wrong email/login '" + login + "')");
|
||||||
}
|
}
|
||||||
// Check the password:
|
// Check the password:
|
||||||
final String passwodCheck = getSHA512("login='" + login + "';pass='" + user.password + "';date='" + time + "'");
|
final String passwordCheck = getSHA512(
|
||||||
if (!passwodCheck.contentEquals(password)) {
|
"login='" + login + "';pass='" + user.password + "';date='" + time + "'");
|
||||||
|
if (!passwordCheck.contentEquals(password)) {
|
||||||
throw new FailException(Response.Status.PRECONDITION_FAILED, "Password error ...");
|
throw new FailException(Response.Status.PRECONDITION_FAILED, "Password error ...");
|
||||||
}
|
}
|
||||||
LOGGER.debug(" ==> pass nearly all test : admin={} blocked={} removed={}", user.admin, user.blocked,
|
LOGGER.debug(" ==> pass nearly all test : admin={} blocked={} removed={}", user.admin, user.blocked,
|
||||||
|
@ -2,20 +2,25 @@ package org.kar.karso.migration;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.kar.archidata.dataAccess.DataAccess;
|
||||||
import org.kar.archidata.migration.MigrationSqlStep;
|
import org.kar.archidata.migration.MigrationSqlStep;
|
||||||
|
import org.kar.archidata.tools.UuidUtils;
|
||||||
import org.kar.karso.model.Application;
|
import org.kar.karso.model.Application;
|
||||||
import org.kar.karso.model.ApplicationToken;
|
import org.kar.karso.model.ApplicationToken;
|
||||||
import org.kar.karso.model.Right;
|
import org.kar.karso.model.Right;
|
||||||
import org.kar.karso.model.RightDescription;
|
import org.kar.karso.model.RightDescription;
|
||||||
import org.kar.karso.model.Settings;
|
import org.kar.karso.model.Settings;
|
||||||
import org.kar.karso.model.UserAuth;
|
import org.kar.karso.model.UserAuth;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class Initialization extends MigrationSqlStep {
|
public class Initialization extends MigrationSqlStep {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class);
|
||||||
|
|
||||||
public static final int KARSO_INITIALISATION_ID = 1;
|
public static final int KARSO_INITIALISATION_ID = 1;
|
||||||
|
|
||||||
public static final List<Class<?>> CLASSES_BASE = List.of(Settings.class, UserAuth.class, Application.class,
|
public static final List<Class<?>> LIST_OF_COMMON_CLASSES = List.of(Settings.class, UserAuth.class,
|
||||||
ApplicationToken.class, RightDescription.class, Right.class);
|
Application.class, ApplicationToken.class, RightDescription.class, Right.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -28,7 +33,7 @@ public class Initialization extends MigrationSqlStep {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateStep() throws Exception {
|
public void generateStep() throws Exception {
|
||||||
for (final Class<?> clazz : CLASSES_BASE) {
|
for (final Class<?> clazz : LIST_OF_COMMON_CLASSES) {
|
||||||
addClass(clazz);
|
addClass(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,10 +49,15 @@ public class Initialization extends MigrationSqlStep {
|
|||||||
(1, 'karadmin', '0ddcac5ede3f1300a1ce5948ab15112f2810130531d578ab8bc4dc131652d7cf7a3ff6e827eb957bff43bc2c65a6a1d46722e5b3a2343ac3176a33ea7250080b',
|
(1, 'karadmin', '0ddcac5ede3f1300a1ce5948ab15112f2810130531d578ab8bc4dc131652d7cf7a3ff6e827eb957bff43bc2c65a6a1d46722e5b3a2343ac3176a33ea7250080b',
|
||||||
'admin@admin.ZZZ', 1);
|
'admin@admin.ZZZ', 1);
|
||||||
""");
|
""");
|
||||||
|
final String data = UuidUtils.nextUUID().toString();
|
||||||
addAction("""
|
addAction("""
|
||||||
INSERT INTO `user_link_application` (`object1Id`, `object2Id`)
|
INSERT INTO `user_link_application` (`uuid`, `object1Id`, `object2Id`)
|
||||||
VALUES ('1', '1');
|
VALUES (UUID_TO_BIN('%s'), '1', '1');
|
||||||
""");
|
""".formatted(data), "mysql");
|
||||||
|
addAction("""
|
||||||
|
INSERT INTO `user_link_application` (`uuid`, `object1Id`, `object2Id`)
|
||||||
|
VALUES ('%s', '1', '1');
|
||||||
|
""".formatted(data), "sqlite");
|
||||||
addAction("""
|
addAction("""
|
||||||
INSERT INTO `settings` (`key`, `right`, `type`, `value`) VALUES
|
INSERT INTO `settings` (`key`, `right`, `type`, `value`) VALUES
|
||||||
('SIGN_UP_ENABLE', 'rwr-r-', 'BOOLEAN', 'false'),
|
('SIGN_UP_ENABLE', 'rwr-r-', 'BOOLEAN', 'false'),
|
||||||
@ -83,4 +93,25 @@ public class Initialization extends MigrationSqlStep {
|
|||||||
display();
|
display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void dropAll() {
|
||||||
|
for (final Class<?> element : LIST_OF_COMMON_CLASSES) {
|
||||||
|
try {
|
||||||
|
DataAccess.drop(element);
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
LOGGER.error("Fail to drop table !!!!!!");
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanAll() {
|
||||||
|
for (final Class<?> element : LIST_OF_COMMON_CLASSES) {
|
||||||
|
try {
|
||||||
|
DataAccess.cleanAll(element);
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
LOGGER.error("Fail to clean table !!!!!!");
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ public class Migration20231015 extends MigrationSqlStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateStep() throws Exception {
|
public void generateStep() {
|
||||||
|
|
||||||
for (final String elem : List.of("application", "applicationToken", "right", "rightDescription", "settings",
|
for (final String elem : List.of("application", "applicationToken", "right", "rightDescription", "settings",
|
||||||
"user", "user_link_application")) { //, "user_link_cover")) {
|
"user", "user_link_application")) { //, "user_link_cover")) {
|
||||||
@ -30,7 +30,6 @@ public class Migration20231015 extends MigrationSqlStep {
|
|||||||
RENAME COLUMN `modify_date` TO `updatedAt`;
|
RENAME COLUMN `modify_date` TO `updatedAt`;
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
display();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public class Migration20231126 extends MigrationSqlStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateStep() throws Exception {
|
public void generateStep() {
|
||||||
// update migration update (last one)
|
// update migration update (last one)
|
||||||
addAction(
|
addAction(
|
||||||
"""
|
"""
|
||||||
|
@ -23,7 +23,7 @@ public class Migration20240515 extends MigrationSqlStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateStep() throws Exception {
|
public void generateStep() {
|
||||||
// update migration update (last one)
|
// update migration update (last one)
|
||||||
addAction("""
|
addAction("""
|
||||||
ALTER TABLE `user_link_application` ADD `uuid` binary(16) AFTER `id`;
|
ALTER TABLE `user_link_application` ADD `uuid` binary(16) AFTER `id`;
|
||||||
@ -35,9 +35,13 @@ public class Migration20240515 extends MigrationSqlStep {
|
|||||||
elem.uuid = UuidUtils.nextUUID();
|
elem.uuid = UuidUtils.nextUUID();
|
||||||
}
|
}
|
||||||
for (final UUIDConversion elem : datas) {
|
for (final UUIDConversion elem : datas) {
|
||||||
DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("data"));
|
DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("user_link_application"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
addAction("""
|
||||||
|
ALTER TABLE `user_link_application`
|
||||||
|
CHANGE `id` `id` bigint;
|
||||||
|
""");
|
||||||
addAction("""
|
addAction("""
|
||||||
ALTER TABLE `user_link_application` DROP PRIMARY KEY;
|
ALTER TABLE `user_link_application` DROP PRIMARY KEY;
|
||||||
""");
|
""");
|
||||||
@ -52,7 +56,7 @@ public class Migration20240515 extends MigrationSqlStep {
|
|||||||
|
|
||||||
addAction("""
|
addAction("""
|
||||||
ALTER TABLE `user_link_application`
|
ALTER TABLE `user_link_application`
|
||||||
ADD `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Deleted state' AFTER `uuid`;
|
DROP `id`;
|
||||||
""");
|
""");
|
||||||
|
|
||||||
addAction("""
|
addAction("""
|
||||||
|
89
back/test/src/test/kar/karso/TestUsers.java
Normal file
89
back/test/src/test/kar/karso/TestUsers.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package test.kar.karso;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.kar.archidata.db.DBEntry;
|
||||||
|
import org.kar.archidata.exception.RESTErrorResponseExeption;
|
||||||
|
import org.kar.archidata.model.GetToken;
|
||||||
|
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||||
|
import org.kar.archidata.tools.RESTApi;
|
||||||
|
import org.kar.karso.migration.Initialization;
|
||||||
|
import org.kar.karso.model.DataGetToken;
|
||||||
|
import org.kar.karso.model.UserAuthGet;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ExtendWith(StepwiseExtension.class)
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
public class TestUsers {
|
||||||
|
private final static Logger LOGGER = LoggerFactory.getLogger(TestUsers.class);
|
||||||
|
public final static String ENDPOINT_NAME = "users/";
|
||||||
|
|
||||||
|
static WebLauncherTest webInterface = null;
|
||||||
|
static RESTApi api = null;
|
||||||
|
|
||||||
|
private static long idTest;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void configureWebServer() throws InterruptedException, RESTErrorResponseExeption, IOException {
|
||||||
|
LOGGER.info("configure server ...");
|
||||||
|
webInterface = new WebLauncherTest();
|
||||||
|
LOGGER.info("Clean previous table");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Initialization.dropAll();
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
LOGGER.error("plop: {}", ex.getLocalizedMessage());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("Create DB");
|
||||||
|
try {
|
||||||
|
webInterface.migrateDB();
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
LOGGER.error("Detect an error: {}", ex.getMessage());
|
||||||
|
}
|
||||||
|
LOGGER.info("Start REST (BEGIN)");
|
||||||
|
webInterface.process();
|
||||||
|
LOGGER.info("Start REST (DONE)");
|
||||||
|
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||||
|
final GetToken result = api.post(GetToken.class, "users/get_token",
|
||||||
|
DataGetToken.generate("karadmin", "v1", "202515252", "adminA@666"));
|
||||||
|
api.setToken(result.jwt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void stopWebServer() throws IOException {
|
||||||
|
LOGGER.info("Kill the web server");
|
||||||
|
webInterface.stop();
|
||||||
|
webInterface = null;
|
||||||
|
LOGGER.info("Remove the test db");
|
||||||
|
DBEntry.closeAllForceMode();
|
||||||
|
ConfigBaseVariable.clearAllValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(1)
|
||||||
|
@Test
|
||||||
|
public void getsValue() throws RESTErrorResponseExeption, IOException, InterruptedException {
|
||||||
|
final List<UserAuthGet> listUsers = api.gets(UserAuthGet.class, TestUsers.ENDPOINT_NAME);
|
||||||
|
Assertions.assertNotNull(listUsers);
|
||||||
|
Assertions.assertEquals(1, listUsers.size());
|
||||||
|
Assertions.assertEquals(1, listUsers.get(0).id);
|
||||||
|
Assertions.assertEquals(true, listUsers.get(0).admin);
|
||||||
|
Assertions.assertEquals(false, listUsers.get(0).blocked);
|
||||||
|
Assertions.assertEquals(false, listUsers.get(0).avatar);
|
||||||
|
Assertions.assertEquals("karadmin", listUsers.get(0).login);
|
||||||
|
Assertions.assertEquals("admin@admin.ZZZ", listUsers.get(0).email);
|
||||||
|
}
|
||||||
|
}
|
@ -21,31 +21,31 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^18.0.0",
|
"@angular/animations": "^18.0.1",
|
||||||
"@angular/cdk": "^18.0.0",
|
"@angular/cdk": "^18.0.1",
|
||||||
"@angular/common": "^18.0.0",
|
"@angular/common": "^18.0.1",
|
||||||
"@angular/compiler": "^18.0.0",
|
"@angular/compiler": "^18.0.1",
|
||||||
"@angular/core": "^18.0.0",
|
"@angular/core": "^18.0.1",
|
||||||
"@angular/forms": "^18.0.0",
|
"@angular/forms": "^18.0.1",
|
||||||
"@angular/material": "^18.0.0",
|
"@angular/material": "^18.0.1",
|
||||||
"@angular/platform-browser": "^18.0.0",
|
"@angular/platform-browser": "^18.0.1",
|
||||||
"@angular/platform-browser-dynamic": "^18.0.0",
|
"@angular/platform-browser-dynamic": "^18.0.1",
|
||||||
"@angular/router": "^18.0.0",
|
"@angular/router": "^18.0.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"zone.js": "^0.14.6",
|
"zone.js": "^0.14.6",
|
||||||
"zod": "3.23.8",
|
"zod": "3.23.8",
|
||||||
"@kangaroo-and-rabbit/kar-cw": "^0.4.0"
|
"@kangaroo-and-rabbit/kar-cw": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^18.0.1",
|
"@angular-devkit/build-angular": "^18.0.2",
|
||||||
"@angular-eslint/builder": "17.5.2",
|
"@angular-eslint/builder": "18.0.1",
|
||||||
"@angular-eslint/eslint-plugin": "17.5.2",
|
"@angular-eslint/eslint-plugin": "18.0.1",
|
||||||
"@angular-eslint/eslint-plugin-template": "17.5.2",
|
"@angular-eslint/eslint-plugin-template": "18.0.1",
|
||||||
"@angular-eslint/schematics": "17.5.2",
|
"@angular-eslint/schematics": "18.0.1",
|
||||||
"@angular-eslint/template-parser": "17.5.2",
|
"@angular-eslint/template-parser": "18.0.1",
|
||||||
"@angular/cli": "^18.0.1",
|
"@angular/cli": "^18.0.2",
|
||||||
"@angular/compiler-cli": "^18.0.0",
|
"@angular/compiler-cli": "^18.0.1",
|
||||||
"@angular/language-service": "^18.0.0",
|
"@angular/language-service": "^18.0.1",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"jasmine": "^5.1.0",
|
"jasmine": "^5.1.0",
|
||||||
@ -57,7 +57,7 @@
|
|||||||
"karma-jasmine": "^5.1.0",
|
"karma-jasmine": "^5.1.0",
|
||||||
"karma-jasmine-html-reporter": "^2.1.0",
|
"karma-jasmine-html-reporter": "^2.1.0",
|
||||||
"karma-spec-reporter": "^0.0.36",
|
"karma-spec-reporter": "^0.0.36",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.0",
|
||||||
"npm-check-updates": "^16.14.20",
|
"npm-check-updates": "^16.14.20",
|
||||||
"tslib": "^2.6.2"
|
"tslib": "^2.6.2"
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg18"
|
id="svg18"
|
||||||
sodipodi:docname="ikon_red.svg"
|
sodipodi:docname="ikon_red.svg"
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@ -72,9 +72,9 @@
|
|||||||
borderopacity="1.0"
|
borderopacity="1.0"
|
||||||
inkscape:pageopacity="0.0"
|
inkscape:pageopacity="0.0"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="5.6"
|
inkscape:zoom="7.9195959"
|
||||||
inkscape:cx="42.410714"
|
inkscape:cx="89.966711"
|
||||||
inkscape:cy="110.625"
|
inkscape:cy="177.91312"
|
||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
showgrid="true"
|
showgrid="true"
|
||||||
@ -85,10 +85,18 @@
|
|||||||
inkscape:window-x="0"
|
inkscape:window-x="0"
|
||||||
inkscape:window-y="20"
|
inkscape:window-y="20"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
inkscape:pagecheckerboard="0">
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#d1d1d1">
|
||||||
<inkscape:grid
|
<inkscape:grid
|
||||||
type="xygrid"
|
type="xygrid"
|
||||||
id="grid4504" />
|
id="grid4504"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingy="1"
|
||||||
|
spacingx="1"
|
||||||
|
units="px"
|
||||||
|
visible="true" />
|
||||||
</sodipodi:namedview>
|
</sodipodi:namedview>
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata5">
|
id="metadata5">
|
||||||
@ -114,11 +122,9 @@
|
|||||||
transform="matrix(0.8407653,0,0,0.83753055,-37.28971,3.4402954)"
|
transform="matrix(0.8407653,0,0,0.83753055,-37.28971,3.4402954)"
|
||||||
aria-label="K">
|
aria-label="K">
|
||||||
<path
|
<path
|
||||||
sodipodi:nodetypes="ccccccccccccc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path823-5"
|
id="path823-5"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:84.55024719px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;opacity:0.775;fill:#2b3137;fill-opacity:1;stroke-width:2.11405313;filter:url(#filter5338);stroke-miterlimit:4;stroke-dasharray:none"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:84.55024719px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;opacity:0.775;fill:#2b3137;fill-opacity:1;stroke-width:2.11405313;filter:url(#filter5338);stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
d="m 65.200546,279.9533 h 8.949095 v 27.37877 l 25.568842,-27.37877 6.392207,6.84469 -20.455071,21.90302 20.455071,27.37876 -6.392207,5.47576 -19.176632,-27.37877 -6.39221,6.84469 v 20.53408 h -8.949095 z" />
|
d="M 65.200545 279.95309 L 65.200545 341.55532 L 74.14964 341.55532 L 74.14964 321.02125 L 80.541851 314.17676 L 99.718483 341.55532 L 106.11069 336.07998 L 85.655619 308.7008 L 106.11069 286.7982 L 99.718483 279.95309 L 74.14964 307.33227 L 74.14964 279.95309 L 65.200545 279.95309 z M 69.586585 307.95792 C 71.270821 307.95521 72.163105 308.76519 72.164982 309.94037 C 72.166858 311.11555 71.276967 311.92813 69.592731 311.93085 C 67.946259 311.9335 67.061695 311.12357 67.059818 309.94839 C 67.057941 308.77322 67.940113 307.96057 69.586585 307.95792 z M 69.588429 309.10309 C 68.568824 309.10473 68.017826 309.4316 68.01865 309.94716 C 68.019473 310.46272 68.571283 310.78793 69.590887 310.78629 C 70.655808 310.78458 71.206973 310.45717 71.20615 309.94161 C 71.205327 309.42604 70.653349 309.10138 69.588429 309.10309 z M 70.651134 317.13779 C 71.466818 317.13648 72.177771 317.82535 72.179733 319.0536 C 72.180798 319.7208 71.940317 320.4034 71.472902 320.93487 L 70.70891 320.29194 C 71.010421 319.91995 71.221049 319.45722 71.220287 318.97956 C 71.219524 318.50191 71.038049 318.28194 70.788812 318.28234 C 70.441392 318.2829 70.351355 318.5789 70.155738 319.04928 L 69.884683 319.68666 C 69.681646 320.24045 69.259204 320.7412 68.541704 320.74236 C 67.726021 320.74367 67.075662 320.0017 67.073955 318.93267 C 67.072998 318.33371 67.298319 317.73449 67.720551 317.28649 L 68.424309 317.85414 C 68.175617 318.19572 68.032626 318.50667 68.033401 318.9919 C 68.033994 319.36341 68.192626 319.61369 68.479626 319.61323 C 68.774179 319.61276 68.886895 319.27856 69.059842 318.80063 L 69.315531 318.20151 C 69.556173 317.54909 69.956292 317.13891 70.651134 317.13779 z M 72.09983 325.98324 L 72.102289 327.23453 L 70.32845 328.18534 L 70.32968 328.76904 L 72.104747 328.76595 L 72.106591 329.88027 L 67.18213 329.88829 L 67.179057 328.13722 C 67.177386 327.09093 67.538843 326.22575 68.7095 326.22387 C 69.434552 326.2227 69.895571 326.57849 70.130538 327.10126 L 72.09983 325.98324 z M 68.711344 327.32338 C 68.227976 327.32416 68.061959 327.6353 68.062903 328.22668 L 68.064133 328.77274 L 69.445833 328.77027 L 69.445219 328.22422 C 69.444274 327.63284 69.194712 327.3226 68.711344 327.32338 z M 72.114581 335.0286 L 72.116425 336.2114 L 70.946159 336.5088 L 70.948618 338.00258 L 72.119499 338.30368 L 72.121342 339.44145 L 67.195038 337.91003 L 67.192579 336.57544 L 72.114581 335.0286 z M 70.078294 336.73771 L 69.625307 336.85248 C 69.134592 336.98216 68.560497 337.13471 68.039547 337.24921 L 68.039547 337.27945 C 68.560872 337.39992 69.13541 337.53513 69.626536 337.66323 L 70.079523 337.77614 L 70.078294 336.73771 z " />
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
id="text821"
|
id="text821"
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 7.6 KiB |
@ -4,389 +4,442 @@
|
|||||||
* @license MPL-2
|
* @license MPL-2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RestErrorResponse } from "./model";
|
import { RestErrorResponse, isRestErrorResponse } from "./model";
|
||||||
|
|
||||||
export enum HTTPRequestModel {
|
export enum HTTPRequestModel {
|
||||||
DELETE = "DELETE",
|
DELETE = "DELETE",
|
||||||
GET = "GET",
|
GET = "GET",
|
||||||
PATCH = "PATCH",
|
PATCH = "PATCH",
|
||||||
POST = "POST",
|
POST = "POST",
|
||||||
PUT = "PUT",
|
PUT = "PUT",
|
||||||
}
|
}
|
||||||
export enum HTTPMimeType {
|
export enum HTTPMimeType {
|
||||||
ALL = "*/*",
|
ALL = "*/*",
|
||||||
CSV = "text/csv",
|
CSV = "text/csv",
|
||||||
IMAGE = "image/*",
|
IMAGE = "image/*",
|
||||||
IMAGE_JPEG = "image/jpeg",
|
IMAGE_JPEG = "image/jpeg",
|
||||||
IMAGE_PNG = "image/png",
|
IMAGE_PNG = "image/png",
|
||||||
JSON = "application/json",
|
JSON = "application/json",
|
||||||
MULTIPART = "multipart/form-data",
|
MULTIPART = "multipart/form-data",
|
||||||
OCTET_STREAM = "application/octet-stream",
|
OCTET_STREAM = "application/octet-stream",
|
||||||
TEXT_PLAIN = "text/plain",
|
TEXT_PLAIN = "text/plain",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RESTConfig {
|
export interface RESTConfig {
|
||||||
// base of the server: http(s)://my.server.org/plop/api/
|
// base of the server: http(s)://my.server.org/plop/api/
|
||||||
server: string;
|
server: string;
|
||||||
// Token to access of the data.
|
// Token to access of the data.
|
||||||
token?: string;
|
token?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RESTModel {
|
export interface RESTModel {
|
||||||
// base of the local API request: "sheep/{id}".
|
// base of the local API request: "sheep/{id}".
|
||||||
endPoint: string;
|
endPoint: string;
|
||||||
// Type of the request.
|
// Type of the request.
|
||||||
requestType?: HTTPRequestModel;
|
requestType?: HTTPRequestModel;
|
||||||
// Input type requested.
|
// Input type requested.
|
||||||
accept?: HTTPMimeType;
|
accept?: HTTPMimeType;
|
||||||
// Content of the local data.
|
// Content of the local data.
|
||||||
contentType?: HTTPMimeType;
|
contentType?: HTTPMimeType;
|
||||||
// Mode of the TOKEN in URL or Header (?token:${tokenInUrl})
|
// Mode of the TOKEN in URL or Header (?token:${tokenInUrl})
|
||||||
tokenInUrl?: boolean;
|
tokenInUrl?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelResponseHttp {
|
export interface ModelResponseHttp {
|
||||||
status: number;
|
status: number;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNullOrUndefined(data: any): data is undefined | null {
|
function isNullOrUndefined(data: any): data is undefined | null {
|
||||||
return data === undefined || data === null;
|
return data === undefined || data === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic progression callback
|
// generic progression callback
|
||||||
export type ProgressCallback = (count: number, total: number) => void;
|
export type ProgressCallback = (count: number, total: number) => void;
|
||||||
|
|
||||||
export interface RESTAbort {
|
export interface RESTAbort {
|
||||||
abort?: () => boolean;
|
abort?: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rest generic callback have a basic model to upload and download advancement.
|
// Rest generic callback have a basic model to upload and download advancement.
|
||||||
export interface RESTCallbacks {
|
export interface RESTCallbacks {
|
||||||
progressUpload?: ProgressCallback;
|
progressUpload?: ProgressCallback;
|
||||||
progressDownload?: ProgressCallback;
|
progressDownload?: ProgressCallback;
|
||||||
abortHandle?: RESTAbort;
|
abortHandle?: RESTAbort;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RESTRequestType {
|
export interface RESTRequestType {
|
||||||
restModel: RESTModel;
|
restModel: RESTModel;
|
||||||
restConfig: RESTConfig;
|
restConfig: RESTConfig;
|
||||||
data?: any;
|
data?: any;
|
||||||
params?: object;
|
params?: object;
|
||||||
queries?: object;
|
queries?: object;
|
||||||
callback?: RESTCallbacks;
|
callback?: RESTCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAll(input, searchValue, replaceValue) {
|
function replaceAll(input, searchValue, replaceValue) {
|
||||||
return input.split(searchValue).join(replaceValue);
|
return input.split(searchValue).join(replaceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTrailingSlashes(input: string): string {
|
function removeTrailingSlashes(input: string): string {
|
||||||
if (isNullOrUndefined(input)) {
|
if (isNullOrUndefined(input)) {
|
||||||
return "undefined";
|
return "undefined";
|
||||||
}
|
}
|
||||||
return input.replace(/\/+$/, "");
|
return input.replace(/\/+$/, "");
|
||||||
}
|
}
|
||||||
function removeLeadingSlashes(input: string): string {
|
function removeLeadingSlashes(input: string): string {
|
||||||
if (isNullOrUndefined(input)) {
|
if (isNullOrUndefined(input)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return input.replace(/^\/+/, "");
|
return input.replace(/^\/+/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTUrl({
|
export function RESTUrl({
|
||||||
restModel,
|
restModel,
|
||||||
restConfig,
|
restConfig,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
}: RESTRequestType): string {
|
}: RESTRequestType): string {
|
||||||
// Create the URL PATH:
|
// Create the URL PATH:
|
||||||
let generateUrl = `${removeTrailingSlashes(
|
let generateUrl = `${removeTrailingSlashes(
|
||||||
restConfig.server
|
restConfig.server
|
||||||
)}/${removeLeadingSlashes(restModel.endPoint)}`;
|
)}/${removeLeadingSlashes(restModel.endPoint)}`;
|
||||||
if (params !== undefined) {
|
if (params !== undefined) {
|
||||||
for (let key of Object.keys(params)) {
|
for (let key of Object.keys(params)) {
|
||||||
generateUrl = replaceAll(generateUrl, `{${key}}`, `${params[key]}`);
|
generateUrl = replaceAll(generateUrl, `{${key}}`, `${params[key]}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
queries === undefined &&
|
||||||
|
(restConfig.token === undefined || restModel.tokenInUrl !== true)
|
||||||
|
) {
|
||||||
|
return generateUrl;
|
||||||
|
}
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
if (queries !== undefined) {
|
||||||
|
for (let key of Object.keys(queries)) {
|
||||||
|
const value = queries[key];
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
for (const element of value) {
|
||||||
|
searchParams.append(`${key}`, `${element}`);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
searchParams.append(`${key}`, `${value}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (
|
}
|
||||||
queries === undefined &&
|
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
||||||
(restConfig.token === undefined || restModel.tokenInUrl !== true)
|
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
|
||||||
) {
|
}
|
||||||
return generateUrl;
|
return generateUrl + "?" + searchParams.toString();
|
||||||
}
|
|
||||||
const searchParams = new URLSearchParams();
|
|
||||||
if (queries !== undefined) {
|
|
||||||
for (let key of Object.keys(queries)) {
|
|
||||||
const value = queries[key];
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
for (const element of value) {
|
|
||||||
searchParams.append(`${key}`, `${element}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
searchParams.append(`${key}`, `${value}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
|
||||||
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
|
|
||||||
}
|
|
||||||
return generateUrl + "?" + searchParams.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchProgress(
|
export function fetchProgress(
|
||||||
generateUrl: string,
|
generateUrl: string,
|
||||||
{
|
{
|
||||||
method,
|
method,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
}: {
|
}: {
|
||||||
method: HTTPRequestModel;
|
method: HTTPRequestModel;
|
||||||
headers: any;
|
headers: any;
|
||||||
body: any;
|
body: any;
|
||||||
},
|
},
|
||||||
{ progressUpload, progressDownload, abortHandle }: RESTCallbacks
|
{ progressUpload, progressDownload, abortHandle }: RESTCallbacks
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const xhr: {
|
const xhr: {
|
||||||
io?: XMLHttpRequest;
|
io?: XMLHttpRequest;
|
||||||
} = {
|
} = {
|
||||||
io: new XMLHttpRequest(),
|
io: new XMLHttpRequest(),
|
||||||
};
|
};
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Stream the upload progress
|
// Stream the upload progress
|
||||||
if (progressUpload) {
|
if (progressUpload) {
|
||||||
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
||||||
if (dataEvent.lengthComputable) {
|
if (dataEvent.lengthComputable) {
|
||||||
progressUpload(dataEvent.loaded, dataEvent.total);
|
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// Stream the download progress
|
});
|
||||||
if (progressDownload) {
|
}
|
||||||
xhr.io?.addEventListener("progress", (dataEvent) => {
|
// Stream the download progress
|
||||||
if (dataEvent.lengthComputable) {
|
if (progressDownload) {
|
||||||
progressDownload(dataEvent.loaded, dataEvent.total);
|
xhr.io?.addEventListener("progress", (dataEvent) => {
|
||||||
}
|
if (dataEvent.lengthComputable) {
|
||||||
});
|
progressDownload(dataEvent.loaded, dataEvent.total);
|
||||||
}
|
}
|
||||||
if (abortHandle) {
|
});
|
||||||
abortHandle.abort = () => {
|
}
|
||||||
if (xhr.io) {
|
if (abortHandle) {
|
||||||
console.log(`Request abort on the XMLHttpRequest: ${generateUrl}`);
|
abortHandle.abort = () => {
|
||||||
xhr.io.abort();
|
if (xhr.io) {
|
||||||
return true;
|
console.log(`Request abort on the XMLHttpRequest: ${generateUrl}`);
|
||||||
}
|
xhr.io.abort();
|
||||||
console.log(
|
return true;
|
||||||
`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// Check if we have an internal Fail:
|
console.log(
|
||||||
xhr.io?.addEventListener("error", () => {
|
`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`
|
||||||
xhr.io = undefined;
|
);
|
||||||
reject(new TypeError("Failed to fetch"));
|
return false;
|
||||||
});
|
};
|
||||||
|
}
|
||||||
// Capture the end of the stream
|
// Check if we have an internal Fail:
|
||||||
xhr.io?.addEventListener("loadend", () => {
|
xhr.io?.addEventListener("error", () => {
|
||||||
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
xhr.io = undefined;
|
||||||
return;
|
reject(new TypeError("Failed to fetch"));
|
||||||
}
|
|
||||||
if (xhr.io?.status === 0) {
|
|
||||||
//the stream has been aborted
|
|
||||||
reject(new TypeError("Fetch has been aborted"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Stream is ended, transform in a generic response:
|
|
||||||
const response = new Response(xhr.io.response, {
|
|
||||||
status: xhr.io.status,
|
|
||||||
statusText: xhr.io.statusText,
|
|
||||||
});
|
|
||||||
const headersArray = replaceAll(
|
|
||||||
xhr.io.getAllResponseHeaders().trim(),
|
|
||||||
"\r\n",
|
|
||||||
"\n"
|
|
||||||
).split("\n");
|
|
||||||
headersArray.forEach(function (header) {
|
|
||||||
const firstColonIndex = header.indexOf(":");
|
|
||||||
if (firstColonIndex !== -1) {
|
|
||||||
const key = header.substring(0, firstColonIndex).trim();
|
|
||||||
const value = header.substring(firstColonIndex + 1).trim();
|
|
||||||
response.headers.set(key, value);
|
|
||||||
} else {
|
|
||||||
response.headers.set(header, "");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
xhr.io = undefined;
|
|
||||||
resolve(response);
|
|
||||||
});
|
|
||||||
xhr.io?.open(method, generateUrl, true);
|
|
||||||
if (!isNullOrUndefined(headers)) {
|
|
||||||
for (const [key, value] of Object.entries(headers)) {
|
|
||||||
xhr.io?.setRequestHeader(key, value as string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xhr.io?.send(body);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Capture the end of the stream
|
||||||
|
xhr.io?.addEventListener("loadend", () => {
|
||||||
|
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (xhr.io?.status === 0) {
|
||||||
|
//the stream has been aborted
|
||||||
|
reject(new TypeError("Fetch has been aborted"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Stream is ended, transform in a generic response:
|
||||||
|
const response = new Response(xhr.io.response, {
|
||||||
|
status: xhr.io.status,
|
||||||
|
statusText: xhr.io.statusText,
|
||||||
|
});
|
||||||
|
const headersArray = replaceAll(
|
||||||
|
xhr.io.getAllResponseHeaders().trim(),
|
||||||
|
"\r\n",
|
||||||
|
"\n"
|
||||||
|
).split("\n");
|
||||||
|
headersArray.forEach(function (header) {
|
||||||
|
const firstColonIndex = header.indexOf(":");
|
||||||
|
if (firstColonIndex !== -1) {
|
||||||
|
const key = header.substring(0, firstColonIndex).trim();
|
||||||
|
const value = header.substring(firstColonIndex + 1).trim();
|
||||||
|
response.headers.set(key, value);
|
||||||
|
} else {
|
||||||
|
response.headers.set(header, "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
xhr.io = undefined;
|
||||||
|
resolve(response);
|
||||||
|
});
|
||||||
|
xhr.io?.open(method, generateUrl, true);
|
||||||
|
if (!isNullOrUndefined(headers)) {
|
||||||
|
for (const [key, value] of Object.entries(headers)) {
|
||||||
|
xhr.io?.setRequestHeader(key, value as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhr.io?.send(body);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTRequest({
|
export function RESTRequest({
|
||||||
restModel,
|
restModel,
|
||||||
restConfig,
|
restConfig,
|
||||||
data,
|
data,
|
||||||
params,
|
params,
|
||||||
queries,
|
queries,
|
||||||
callback,
|
callback,
|
||||||
}: RESTRequestType): Promise<ModelResponseHttp> {
|
}: RESTRequestType): Promise<ModelResponseHttp> {
|
||||||
// Create the URL PATH:
|
// Create the URL PATH:
|
||||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||||
let headers: any = {};
|
let headers: any = {};
|
||||||
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
|
||||||
headers["Authorization"] = `Bearer ${restConfig.token}`;
|
headers["Authorization"] = `Bearer ${restConfig.token}`;
|
||||||
|
}
|
||||||
|
if (restModel.accept !== undefined) {
|
||||||
|
headers["Accept"] = restModel.accept;
|
||||||
|
}
|
||||||
|
if (restModel.requestType !== HTTPRequestModel.GET) {
|
||||||
|
// if Get we have not a content type, the body is empty
|
||||||
|
if (restModel.contentType !== HTTPMimeType.MULTIPART) {
|
||||||
|
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
||||||
|
headers["Content-Type"] = restModel.contentType;
|
||||||
}
|
}
|
||||||
if (restModel.accept !== undefined) {
|
}
|
||||||
headers["Accept"] = restModel.accept;
|
let body = data;
|
||||||
|
if (restModel.contentType === HTTPMimeType.JSON) {
|
||||||
|
body = JSON.stringify(data);
|
||||||
|
} else if (restModel.contentType === HTTPMimeType.MULTIPART) {
|
||||||
|
const formData = new FormData();
|
||||||
|
for (const name in data) {
|
||||||
|
formData.append(name, data[name]);
|
||||||
}
|
}
|
||||||
if (restModel.requestType !== HTTPRequestModel.GET) {
|
body = formData;
|
||||||
// if Get we have not a content type, the body is empty
|
}
|
||||||
if (restModel.contentType !== HTTPMimeType.MULTIPART) {
|
return new Promise((resolve, reject) => {
|
||||||
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
let action: undefined | Promise<Response> = undefined;
|
||||||
headers["Content-Type"] = restModel.contentType;
|
if (
|
||||||
}
|
isNullOrUndefined(callback) ||
|
||||||
|
(isNullOrUndefined(callback.progressDownload) &&
|
||||||
|
isNullOrUndefined(callback.progressUpload) &&
|
||||||
|
isNullOrUndefined(callback.abortHandle))
|
||||||
|
) {
|
||||||
|
// No information needed: call the generic fetch interface
|
||||||
|
action = fetch(generateUrl, {
|
||||||
|
method: restModel.requestType,
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
|
||||||
|
action = fetchProgress(
|
||||||
|
generateUrl,
|
||||||
|
{
|
||||||
|
method: restModel.requestType ?? HTTPRequestModel.GET,
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let body = data;
|
action
|
||||||
if (restModel.contentType === HTTPMimeType.JSON) {
|
.then((response: Response) => {
|
||||||
body = JSON.stringify(data);
|
if (response.status >= 200 && response.status <= 299) {
|
||||||
} else if (restModel.contentType === HTTPMimeType.MULTIPART) {
|
const contentType = response.headers.get("Content-Type");
|
||||||
const formData = new FormData();
|
if (
|
||||||
for (const name in data) {
|
!isNullOrUndefined(restModel.accept) &&
|
||||||
formData.append(name, data[name]);
|
restModel.accept !== contentType
|
||||||
}
|
) {
|
||||||
body = formData;
|
reject({
|
||||||
}
|
name: "Model accept type incompatible",
|
||||||
return new Promise((resolve, reject) => {
|
time: Date().toString(),
|
||||||
let action: undefined | Promise<Response> = undefined;
|
status: 901,
|
||||||
if (
|
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
||||||
isNullOrUndefined(callback) ||
|
statusMessage: "Fetch error",
|
||||||
(isNullOrUndefined(callback.progressDownload) &&
|
error: "rest-tools.ts Wrong type in the message return type",
|
||||||
isNullOrUndefined(callback.progressUpload) &&
|
} as RestErrorResponse);
|
||||||
isNullOrUndefined(callback.abortHandle))
|
} else if (contentType === HTTPMimeType.JSON) {
|
||||||
) {
|
response
|
||||||
// No information needed: call the generic fetch interface
|
.json()
|
||||||
action = fetch(generateUrl, {
|
.then((value: any) => {
|
||||||
method: restModel.requestType,
|
resolve({ status: response.status, data: value });
|
||||||
headers,
|
})
|
||||||
body,
|
.catch((reason: Error) => {
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
|
|
||||||
action = fetchProgress(
|
|
||||||
generateUrl,
|
|
||||||
{
|
|
||||||
method: restModel.requestType ?? HTTPRequestModel.GET,
|
|
||||||
headers,
|
|
||||||
body,
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
action
|
|
||||||
.then((response: Response) => {
|
|
||||||
if (response.status >= 200 && response.status <= 299) {
|
|
||||||
const contentType = response.headers.get("Content-Type");
|
|
||||||
if (
|
|
||||||
!isNullOrUndefined(restModel.accept) &&
|
|
||||||
restModel.accept !== contentType
|
|
||||||
) {
|
|
||||||
reject({
|
|
||||||
name: "Model accept type incompatible",
|
|
||||||
time: Date().toString(),
|
|
||||||
status: 901,
|
|
||||||
error: `REST check wrong type: ${restModel.accept} != ${contentType}`,
|
|
||||||
statusMessage: "Fetch error",
|
|
||||||
message: "rest-tools.ts Wrong type in the message return type",
|
|
||||||
} as RestErrorResponse);
|
|
||||||
} else if (contentType === HTTPMimeType.JSON) {
|
|
||||||
response
|
|
||||||
.json()
|
|
||||||
.then((value: any) => {
|
|
||||||
resolve({ status: response.status, data: value });
|
|
||||||
})
|
|
||||||
.catch((reason: any) => {
|
|
||||||
reject({
|
|
||||||
name: "API serialization error",
|
|
||||||
time: Date().toString(),
|
|
||||||
status: 902,
|
|
||||||
error: `REST parse json fail: ${reason}`,
|
|
||||||
statusMessage: "Fetch parse error",
|
|
||||||
message: "rest-tools.ts Wrong message model to parse",
|
|
||||||
} as RestErrorResponse);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve({ status: response.status, data: response.body });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject({
|
|
||||||
name: "REST return no OK status",
|
|
||||||
time: Date().toString(),
|
|
||||||
status: response.status,
|
|
||||||
error: `${response.body}`,
|
|
||||||
statusMessage: "Fetch code error",
|
|
||||||
message: "rest-tools.ts Wrong return code",
|
|
||||||
} as RestErrorResponse);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error: any) => {
|
|
||||||
reject({
|
reject({
|
||||||
name: "Request fail",
|
name: "API serialization error",
|
||||||
time: Date(),
|
time: Date().toString(),
|
||||||
status: 999,
|
status: 902,
|
||||||
error: error,
|
message: `REST parse json fail: ${reason}`,
|
||||||
statusMessage: "Fetch catch error",
|
statusMessage: "Fetch parse error",
|
||||||
message: "rest-tools.ts detect an error in the fetch request",
|
error: "rest-tools.ts Wrong message model to parse",
|
||||||
|
} as RestErrorResponse);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve({ status: response.status, data: response.body });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// the answer is not correct not a 2XX
|
||||||
|
// clone the response to keep the raw data if case of error:
|
||||||
|
response
|
||||||
|
.clone()
|
||||||
|
.json()
|
||||||
|
.then((value: any) => {
|
||||||
|
if (isRestErrorResponse(value)) {
|
||||||
|
reject(value);
|
||||||
|
} else {
|
||||||
|
response
|
||||||
|
.text()
|
||||||
|
.then((dataError: string) => {
|
||||||
|
reject({
|
||||||
|
name: "API serialization error",
|
||||||
|
time: Date().toString(),
|
||||||
|
status: 903,
|
||||||
|
message: `REST parse error json with wrong type fail. ${dataError}`,
|
||||||
|
statusMessage: "Fetch parse error",
|
||||||
|
error: "rest-tools.ts Wrong message model to parse",
|
||||||
|
} as RestErrorResponse);
|
||||||
|
})
|
||||||
|
.catch((reason: any) => {
|
||||||
|
reject({
|
||||||
|
name: "API serialization error",
|
||||||
|
time: Date().toString(),
|
||||||
|
status: response.status,
|
||||||
|
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||||
|
statusMessage: "Fetch ERROR parse error",
|
||||||
|
error: "rest-tools.ts Wrong message model to parse",
|
||||||
|
} as RestErrorResponse);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason: Error) => {
|
||||||
|
response
|
||||||
|
.text()
|
||||||
|
.then((dataError: string) => {
|
||||||
|
reject({
|
||||||
|
name: "API serialization error",
|
||||||
|
time: Date().toString(),
|
||||||
|
status: response.status,
|
||||||
|
message: `unmanaged error model: ${dataError} with error: ${reason}`,
|
||||||
|
statusMessage: "Fetch ERROR TEXT parse error",
|
||||||
|
error: "rest-tools.ts Wrong message model to parse",
|
||||||
|
} as RestErrorResponse);
|
||||||
|
})
|
||||||
|
.catch((reason: any) => {
|
||||||
|
reject({
|
||||||
|
name: "API serialization error",
|
||||||
|
time: Date().toString(),
|
||||||
|
status: response.status,
|
||||||
|
message: `unmanaged error model: ??? with error: ${reason}`,
|
||||||
|
statusMessage: "Fetch ERROR TEXT FAIL",
|
||||||
|
error: "rest-tools.ts Wrong message model to parse",
|
||||||
|
} as RestErrorResponse);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.catch((error: Error) => {
|
||||||
|
if (isRestErrorResponse(error)) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
name: "Request fail",
|
||||||
|
time: Date(),
|
||||||
|
status: 999,
|
||||||
|
message: error,
|
||||||
|
statusMessage: "Fetch catch error",
|
||||||
|
error: "rest-tools.ts detect an error in the fetch request",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTRequestJson<TYPE>(
|
export function RESTRequestJson<TYPE>(
|
||||||
request: RESTRequestType,
|
request: RESTRequestType,
|
||||||
checker?: (data: any) => data is TYPE
|
checker?: (data: any) => data is TYPE
|
||||||
): Promise<TYPE> {
|
): Promise<TYPE> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
RESTRequest(request)
|
RESTRequest(request)
|
||||||
.then((value: ModelResponseHttp) => {
|
.then((value: ModelResponseHttp) => {
|
||||||
if (isNullOrUndefined(checker)) {
|
if (isNullOrUndefined(checker)) {
|
||||||
console.log(`Have no check of MODEL in API: ${RESTUrl(request)}`);
|
console.log(`Have no check of MODEL in API: ${RESTUrl(request)}`);
|
||||||
resolve(value.data);
|
resolve(value.data);
|
||||||
} else if (checker === undefined || checker(value.data)) {
|
} else if (checker === undefined || checker(value.data)) {
|
||||||
resolve(value.data);
|
resolve(value.data);
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: "Model check fail",
|
name: "Model check fail",
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 950,
|
status: 950,
|
||||||
error: "REST Fail to verify the data",
|
error: "REST Fail to verify the data",
|
||||||
statusMessage: "API cast ERROR",
|
statusMessage: "API cast ERROR",
|
||||||
message: "api.ts Check type as fail",
|
message: "api.ts Check type as fail",
|
||||||
} as RestErrorResponse);
|
} as RestErrorResponse);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((reason: RestErrorResponse) => {
|
.catch((reason: RestErrorResponse) => {
|
||||||
reject(reason);
|
reject(reason);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTRequestVoid(request: RESTRequestType): Promise<void> {
|
export function RESTRequestVoid(request: RESTRequestType): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
RESTRequest(request)
|
RESTRequest(request)
|
||||||
.then((value: ModelResponseHttp) => {
|
.then((value: ModelResponseHttp) => {
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((reason: RestErrorResponse) => {
|
.catch((reason: RestErrorResponse) => {
|
||||||
reject(reason);
|
reject(reason);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
.xdesktop {
|
.xdesktop {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xtablette {
|
.xtablette {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xphone {
|
.xphone {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xmobile {
|
.xmobile {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -17,12 +20,15 @@
|
|||||||
.xdesktop {
|
.xdesktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xtablette {
|
.xtablette {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xphone {
|
.xphone {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xmobile {
|
.xmobile {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@ -32,12 +38,15 @@
|
|||||||
.xdesktop {
|
.xdesktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xtablette {
|
.xtablette {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xphone {
|
.xphone {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xmobile {
|
.xmobile {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@ -206,6 +215,7 @@ html {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.square-button {
|
.square-button {
|
||||||
// background: #b3d4fc;
|
// background: #b3d4fc;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
@ -264,12 +274,15 @@ html {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
background: rgba(0, 0, 0, 0);
|
background: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +315,7 @@ label {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.full-back {
|
.full-back {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -312,12 +326,9 @@ label {
|
|||||||
|
|
||||||
background-image: url('assets/images/ikon_red.svg');
|
background-image: url('assets/images/ikon_red.svg');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
/*
|
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
*/
|
|
||||||
background-size: 80%;
|
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
|
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user