plop
This commit is contained in:
parent
2fcb9403bb
commit
307a091178
@ -106,4 +106,4 @@ EXPOSE 80
|
||||
HEALTHCHECK --start-period=10s --start-interval=2s --interval=30s --timeout=5s --retries=10 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:80/api/health_check || exit 1
|
||||
|
||||
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karso.WebLauncher"]
|
||||
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.atriasoft.karso.WebLauncher"]
|
||||
|
@ -53,6 +53,9 @@ Checkstyle configuration that checks the sun coding conventions.
|
||||
<module name="LambdaParameterName"/>
|
||||
<module name="Regexp"/>
|
||||
<module name="RegexpSinglelineJava"/>
|
||||
<module name="UnusedPrivateField">
|
||||
<property name="ignorePattern" value="LOGGER"/>
|
||||
</module>
|
||||
</module>
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||
|
@ -11,7 +11,7 @@ mvn package
|
||||
// download all dependency in out/maven/dependency
|
||||
mvn dependency:copy-dependencies
|
||||
|
||||
java -cp out/maven/kar-karso-0.1.0.jar org.kar.karso.WebLauncher
|
||||
java -cp out/maven/kar-karso-0.1.0.jar org.atriasoft.karso.WebLauncher
|
||||
|
||||
|
||||
// create a single package jar
|
||||
@ -19,7 +19,7 @@ mvn clean compile assembly:single
|
||||
|
||||
|
||||
|
||||
java -cp out/maven/karso-0.1.0-jar-with-dependencies.jar org.kar.karso.WebLauncher
|
||||
java -cp out/maven/karso-0.1.0-jar-with-dependencies.jar org.atriasoft.karso.WebLauncher
|
||||
|
||||
|
||||
|
||||
|
16
back/pom.xml
16
back/pom.xml
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.kar</groupId>
|
||||
<groupId>org.atriasoft</groupId>
|
||||
<artifactId>karso</artifactId>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<properties>
|
||||
@ -10,17 +10,11 @@
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<maven.dependency.version>3.1.1</maven.dependency.version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>gitea</id>
|
||||
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<groupId>org.atria-soft</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.23.6</version>
|
||||
<version>0.28.0</version>
|
||||
</dependency>
|
||||
<!-- Loopback of logger JDK logging API to SLF4J -->
|
||||
<dependency>
|
||||
@ -101,7 +95,7 @@
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<configuration>
|
||||
<mainClass>org.kar.karso.WebLauncher</mainClass>
|
||||
<mainClass>org.atriasoft.karso.WebLauncher</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Create the source bundle -->
|
||||
@ -202,7 +196,7 @@
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>org.kar.karso.WebLauncher</mainClass>
|
||||
<mainClass>org.atriasoft.karso.WebLauncher</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Check the style of the code -->
|
||||
|
@ -1,6 +1,6 @@
|
||||
org.kar..karso.db.host=localhost
|
||||
org.kar..karso.db.port=15306
|
||||
org.kar..karso.db.login=root
|
||||
org.kar..karso.db.password=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
||||
org.kar..karso.db.name=oauth
|
||||
org.kar..karso.address=http://localhost:17080/oauth/api/
|
||||
org.atriasoft..karso.db.host=localhost
|
||||
org.atriasoft..karso.db.port=15306
|
||||
org.atriasoft..karso.db.login=root
|
||||
org.atriasoft..karso.db.password=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh
|
||||
org.atriasoft..karso.db.name=oauth
|
||||
org.atriasoft..karso.address=http://localhost:17080/oauth/api/
|
||||
|
@ -1,17 +0,0 @@
|
||||
package org.kar.karso;
|
||||
|
||||
import org.kar.karso.migration.Initialization;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GenerateApi {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(GenerateApi.class);
|
||||
|
||||
private GenerateApi() {}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
LOGGER.info("Generate API");
|
||||
Initialization.generateObjects();
|
||||
LOGGER.info("STOP the REST server.");
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
package org.kar.karso;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.glassfish.grizzly.http.server.HttpServer;
|
||||
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.kar.archidata.UpdateJwtPublicKey;
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.backup.BackupEngine;
|
||||
import org.kar.archidata.backup.BackupEngine.StoreMode;
|
||||
import org.kar.archidata.catcher.GenericCatcher;
|
||||
import org.kar.archidata.db.DbConfig;
|
||||
import org.kar.archidata.filter.CORSFilter;
|
||||
import org.kar.archidata.filter.OptionFilter;
|
||||
import org.kar.archidata.migration.MigrationEngine;
|
||||
import org.kar.archidata.migration.model.Migration;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.ContextGenericTools;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.kar.karso.api.ApplicationResource;
|
||||
import org.kar.karso.api.ApplicationTokenResource;
|
||||
import org.kar.karso.api.Front;
|
||||
import org.kar.karso.api.HealthCheck;
|
||||
import org.kar.karso.api.PublicKeyResource;
|
||||
import org.kar.karso.api.RightResource;
|
||||
import org.kar.karso.api.SystemConfigResource;
|
||||
import org.kar.karso.api.UserResource;
|
||||
import org.kar.karso.filter.KarsoAuthenticationFilter;
|
||||
import org.kar.karso.migration.Initialization;
|
||||
import org.kar.karso.migration.Migration20231015;
|
||||
import org.kar.karso.migration.Migration20231126;
|
||||
import org.kar.karso.migration.Migration20240515;
|
||||
import org.kar.karso.migration.Migration20250204;
|
||||
import org.kar.karso.model.Application;
|
||||
import org.kar.karso.model.ApplicationToken;
|
||||
import org.kar.karso.model.Right;
|
||||
import org.kar.karso.model.RightDescription;
|
||||
import org.kar.karso.model.Settings;
|
||||
import org.kar.karso.model.UserAuth;
|
||||
import org.kar.karso.util.ConfigVariable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
public class WebLauncher {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
|
||||
protected UpdateJwtPublicKey keyUpdater = null;
|
||||
protected HttpServer server = null;
|
||||
protected BackupEngine backupEngine = new BackupEngine("./backup", StoreMode.JSON);
|
||||
|
||||
public WebLauncher() {
|
||||
ConfigBaseVariable.bdDatabase = "karso";
|
||||
|
||||
this.backupEngine.addClass(Migration.class);
|
||||
this.backupEngine.addClass(Settings.class);
|
||||
this.backupEngine.addClass(UserAuth.class);
|
||||
this.backupEngine.addClass(Application.class);
|
||||
this.backupEngine.addClass(ApplicationToken.class);
|
||||
this.backupEngine.addClass(RightDescription.class);
|
||||
this.backupEngine.addClass(Right.class);
|
||||
}
|
||||
|
||||
private static URI getBaseURI() {
|
||||
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
|
||||
}
|
||||
|
||||
public void migrateDB() throws Exception {
|
||||
WebLauncher.LOGGER.info("Create migration engine");
|
||||
final MigrationEngine migrationEngine = new MigrationEngine();
|
||||
WebLauncher.LOGGER.info("Add initialization");
|
||||
migrationEngine.setInit(new Initialization());
|
||||
WebLauncher.LOGGER.info("Add migration since last version");
|
||||
migrationEngine.add(new Migration20231015());
|
||||
migrationEngine.add(new Migration20231126());
|
||||
migrationEngine.add(new Migration20240515());
|
||||
migrationEngine.add(new Migration20250204());
|
||||
WebLauncher.LOGGER.info("Migrate the DB [START]");
|
||||
migrationEngine.migrateWaitAdmin(new DbConfig());
|
||||
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
WebLauncher.LOGGER.info("[START] application wake UP");
|
||||
final 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 {
|
||||
try {
|
||||
JWTWrapper.initLocalToken(ConfigVariable.getUUIDKeyRoot());
|
||||
} catch (final Exception e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
LOGGER.info("Wait 10 seconds ....");
|
||||
Thread.sleep(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Configure resources
|
||||
// ===================================================================
|
||||
final ResourceConfig rc = new ResourceConfig();
|
||||
|
||||
// add multi-part models ..
|
||||
rc.register(MultiPartFeature.class);
|
||||
// global authentication system
|
||||
rc.register(OptionFilter.class);
|
||||
// remove cors ==> all time called by an other system...
|
||||
rc.register(CORSFilter.class);
|
||||
// global authentication system
|
||||
rc.register(KarsoAuthenticationFilter.class);
|
||||
// register exception catcher
|
||||
GenericCatcher.addAll(rc);
|
||||
// add default resource:
|
||||
rc.register(DataResource.class);
|
||||
rc.register(ApplicationResource.class);
|
||||
rc.register(ApplicationTokenResource.class);
|
||||
rc.register(PublicKeyResource.class);
|
||||
rc.register(RightResource.class);
|
||||
rc.register(SystemConfigResource.class);
|
||||
rc.register(UserResource.class);
|
||||
|
||||
rc.register(HealthCheck.class);
|
||||
rc.register(Front.class);
|
||||
|
||||
ContextGenericTools.addJsr310(rc);
|
||||
|
||||
// add jackson to be discover when we are ins stand-alone server
|
||||
rc.register(JacksonFeature.class);
|
||||
// enable this to show low level request
|
||||
//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());
|
||||
LOGGER.info("Start http Server: {}", getBaseURI());
|
||||
this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
|
||||
final HttpServer serverLink = this.server;
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Stopping server..");
|
||||
serverLink.shutdownNow();
|
||||
}
|
||||
}, "shutdownHook"));
|
||||
|
||||
// ===================================================================
|
||||
// run JERSEY
|
||||
// ===================================================================
|
||||
try {
|
||||
this.server.start();
|
||||
LOGGER.info("Jersey app started at {}", getBaseURI());
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error("There was an error while starting Grizzly HTTP server.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (this.server != null) {
|
||||
this.server.shutdownNow();
|
||||
while (this.server.isStarted()) {
|
||||
LOGGER.info("wait stop");
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
|
||||
package org.kar.karso;
|
||||
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karso.util.ConfigVariable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class WebLauncherEdgeLocal {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherEdgeLocal.class);
|
||||
|
||||
private WebLauncherEdgeLocal() {}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
if (true) {
|
||||
// for local test:
|
||||
ConfigBaseVariable.apiAdress = "http://0.0.0.0:15080/karso/api/";
|
||||
ConfigBaseVariable.dbPort = "3306";
|
||||
ConfigVariable.edge = "true";
|
||||
//ConfigBaseVariable.dbType = "sqlite";
|
||||
//ConfigBaseVariable.dbHost = "./bdd_base.sqlite";
|
||||
|
||||
}
|
||||
WebLauncher.main(args);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
|
||||
package org.kar.karso;
|
||||
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karso.migration.Initialization;
|
||||
import org.kar.karso.util.ConfigVariable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class WebLauncherLocal extends WebLauncher {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class);
|
||||
|
||||
private WebLauncherLocal() {}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
Initialization.generateObjects();
|
||||
final WebLauncherLocal launcher = new WebLauncherLocal();
|
||||
launcher.process();
|
||||
LOGGER.info("end-configure the server & wait finish process:");
|
||||
Thread.currentThread().join();
|
||||
LOGGER.info("STOP the REST server:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process() throws InterruptedException {
|
||||
if (true) {
|
||||
ConfigBaseVariable.apiAdress = "http://0.0.0.0:15080/karso/api/";
|
||||
ConfigBaseVariable.dbPort = "3906";
|
||||
// create a unique key for test ==> not retrieve the token every load...
|
||||
ConfigVariable.uuid_for_key_generation = "lkjlkjlkjlmkjqmwlsdkjqfsdlkf88QJSDMLQKSndmLQKZNERMAL";
|
||||
}
|
||||
try {
|
||||
super.migrateDB();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
while (true) {
|
||||
LOGGER.error("============================================================================");
|
||||
LOGGER.error("== Migration fail ==> waiting intervention of administrator...");
|
||||
LOGGER.error("============================================================================");
|
||||
Thread.sleep(60 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
super.process();
|
||||
}
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.exception.InputException;
|
||||
import org.kar.archidata.exception.SystemException;
|
||||
import org.kar.archidata.filter.GenericContext;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.kar.karso.model.AddUserData;
|
||||
import org.kar.karso.model.Application;
|
||||
import org.kar.karso.model.ApplicationSmall;
|
||||
import org.kar.karso.model.ClientToken;
|
||||
import org.kar.karso.model.RightDescription;
|
||||
import org.kar.karso.model.UserAuth;
|
||||
import org.kar.karso.model.UserLinkApplication;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/application")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class ApplicationResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationResource.class);
|
||||
|
||||
public ApplicationResource() {}
|
||||
|
||||
public List<Long> getUserListOfApplication(final Long userId) {
|
||||
final List<Long> out = new ArrayList<>();
|
||||
List<UserLinkApplication> links = null;
|
||||
try {
|
||||
links = DataAccess.getsWhere(UserLinkApplication.class,
|
||||
new Condition(new QueryCondition("object1id", "=", userId)));
|
||||
} catch (final Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
final String result = "SERVER Internal error";
|
||||
LOGGER.error(" result: {}", result);
|
||||
return out;
|
||||
}
|
||||
for (final UserLinkApplication app : links) {
|
||||
out.add(app.applicationId);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public List<Long> getListOfUsers(final Long applicationId) {
|
||||
final List<Long> out = new ArrayList<>();
|
||||
List<UserLinkApplication> links = null;
|
||||
try {
|
||||
links = DataAccess.getsWhere(UserLinkApplication.class,
|
||||
new Condition(new QueryCondition("object2id", "=", applicationId)));
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
final String result = "SERVER Internal error";
|
||||
LOGGER.error(" result: {}", result);
|
||||
return out;
|
||||
}
|
||||
LOGGER.debug("Find list of user for an application: {}", links);
|
||||
for (final UserLinkApplication app : links) {
|
||||
out.add(app.userId);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic /application/
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@GET
|
||||
@RolesAllowed(value = { "USER", "ADMIN" })
|
||||
public List<Application> gets(@Context final SecurityContext sc) throws Exception {
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.debug("getApplications");
|
||||
// TODO filter with the list of element available in his authorizations ...
|
||||
final List<Application> tmp = DataAccess.gets(Application.class);
|
||||
if (sc.isUserInRole("ADMIN")) {
|
||||
return tmp;
|
||||
}
|
||||
final List<Long> regular = getUserListOfApplication(gc.userByToken.id);
|
||||
final List<Application> out = new ArrayList<>();
|
||||
for (final Application app : tmp) {
|
||||
if (regular.indexOf(app.id) != -1) {
|
||||
out.add(app);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Application create(final Application application) throws Exception {
|
||||
LOGGER.debug("create new application {}", application);
|
||||
// verify login or email is correct:
|
||||
if (application.name == null || application.name.length() < 5) {
|
||||
throw new InputException("name", "create application (name too small: '" + application.name + "')");
|
||||
}
|
||||
if (application.redirect == null || application.redirect.length() < 6) {
|
||||
throw new InputException("redirect",
|
||||
"create application (redirect too small: '" + application.redirect + "')");
|
||||
}
|
||||
application.id = null;
|
||||
application.createdAt = null;
|
||||
application.deleted = null;
|
||||
application.updatedAt = null;
|
||||
final Application tmp = DataAccess.insert(application);
|
||||
return get(tmp.id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic /application/{id}
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Application get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Application.class, id);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Application patch(@PathParam("id") final Long id, @AsyncType(Application.class) final String jsonRequest)
|
||||
throws Exception {
|
||||
DataAccess.updateWithJson(Application.class, id, jsonRequest);
|
||||
return DataAccess.get(Application.class, id);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Produces(value = MediaType.TEXT_PLAIN)
|
||||
public void remove(@Context final SecurityContext sc, @PathParam("id") final long applicationId) throws Exception {
|
||||
DataAccess.delete(Application.class, applicationId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic /{id}/*
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@GET
|
||||
@Path("{id}/users")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
public List<Long> getApplicationUsers(@PathParam("id") final Long applicationId) throws Exception {
|
||||
// special case for SSO: (all user have access on the SSO...).
|
||||
|
||||
LOGGER.debug("Request list of user for an applciation: {}", applicationId);
|
||||
return getListOfUsers(applicationId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic /application/*
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@GET
|
||||
@Path("small")
|
||||
@RolesAllowed(value = { "USER", "ADMIN" })
|
||||
public List<ApplicationSmall> getApplicationsSmall(@Context final SecurityContext sc) throws Exception {
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.debug("getApplications");
|
||||
final List<Application> tmp = DataAccess.gets(Application.class);
|
||||
final List<Long> regular = getUserListOfApplication(gc.userByToken.id);
|
||||
final List<ApplicationSmall> out = new ArrayList<>();
|
||||
for (final Application app : tmp) {
|
||||
if (regular.indexOf(app.id) != -1) {
|
||||
out.add(new ApplicationSmall(app.id, app.name, app.description, app.redirect));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/users")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void addUser(@PathParam("id") final Long applicationId, final AddUserData data) throws Exception {
|
||||
LOGGER.debug("getApplications");
|
||||
try (DBAccess db = DBAccess.createInterface()) {
|
||||
AddOnManyToMany.addLink(db, UserAuth.class, data.userId, "application", applicationId);
|
||||
}
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}/users/${userId}")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
public void removeUser(@PathParam("id") final Long applicationId, @PathParam("userId") final Long userId)
|
||||
throws Exception {
|
||||
LOGGER.debug("getApplications");
|
||||
try (DBAccess db = DBAccess.createInterface()) {
|
||||
AddOnManyToMany.removeLink(db, UserAuth.class, userId, "application", applicationId);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/rights")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
public List<RightDescription> getRightsDescription(@PathParam("id") final Long applicationId) throws Exception {
|
||||
LOGGER.debug("getApplications rights");
|
||||
return DataAccess.getsWhere(RightDescription.class,
|
||||
new Condition(new QueryCondition("applicationId", "=", applicationId)));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("get_token")
|
||||
@RolesAllowed(value = { "USER", "ADMIN" })
|
||||
public ClientToken getClientToken(
|
||||
@Context final SecurityContext sc,
|
||||
@QueryParam("application") final String application) throws Exception {
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.info("get application TOKEN application name='{}'", application);
|
||||
LOGGER.debug("== USER ? {}", gc.userByToken.name);
|
||||
|
||||
if (application == null) {
|
||||
throw new InputException("application", "Input error missing parameter");
|
||||
}
|
||||
String applicationName = application;
|
||||
boolean isDev = false;
|
||||
if (applicationName.endsWith("-dev")) {
|
||||
applicationName = applicationName.substring(0, applicationName.length() - 4);
|
||||
isDev = true;
|
||||
}
|
||||
LOGGER.debug("Search for '{}' base of '{}'", applicationName, application);
|
||||
|
||||
Application appl = null;
|
||||
try {
|
||||
appl = DataAccess.getWhere(Application.class,
|
||||
new Condition(new QueryCondition("name", "=", applicationName)));
|
||||
} catch (final Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
final String result = "SERVER Internal error";
|
||||
LOGGER.debug(" result: {}", result);
|
||||
throw new SystemException("Internal fail request");
|
||||
}
|
||||
|
||||
if (appl == null) {
|
||||
final String result = "Authentiocate-wrong email/login '" + applicationName + "')";
|
||||
LOGGER.error(" result: {}", result);
|
||||
throw new InputException("email/login", "Authentiocate-wrong email/login '" + applicationName + "'");
|
||||
}
|
||||
UserLinkApplication links = null;
|
||||
try {
|
||||
links = DataAccess.getWhere(UserLinkApplication.class,
|
||||
new Condition(new QueryAnd(new QueryCondition("object1id", "=", gc.userByToken.id),
|
||||
new QueryCondition("deleted", "=", 0), new QueryCondition("object2id", "=", appl.id))));
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SystemException("Fail to insert Link");
|
||||
}
|
||||
if (links == null) {
|
||||
throw new SystemException(
|
||||
"Authenticate impossible ==> application not accessible '" + applicationName + "'");
|
||||
}
|
||||
// Get the USER Right
|
||||
final Map<String, PartRight> applicationRight = RightResource.getUserRight(gc.userByToken.id, appl.id);
|
||||
if (!applicationRight.containsKey("USER")) {
|
||||
// If the USER is not override, the system add by default USER
|
||||
applicationRight.put("USER", PartRight.READ_WRITE);
|
||||
}
|
||||
final Map<String, Integer> rightForFront = new HashMap<>();
|
||||
for (final Map.Entry<String, PartRight> entry : applicationRight.entrySet()) {
|
||||
rightForFront.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
final Map<String, Object> outRight = new HashMap<>();
|
||||
// we set the right in the under map to manage multiple application group right.
|
||||
// and in some application user can see other user or all user of the
|
||||
// application
|
||||
outRight.put(applicationName, rightForFront);
|
||||
final String ret = JWTWrapper.generateJWToken(gc.userByToken.id, gc.userByToken.name, "KarAuth",
|
||||
applicationName, outRight, -appl.ttl);
|
||||
// logger.debug(" ==> generate token: {}", ret);
|
||||
String returnAdress = appl.redirect;
|
||||
if (isDev) {
|
||||
returnAdress = appl.redirectDev;
|
||||
}
|
||||
return new ClientToken(returnAdress, ret);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("return")
|
||||
@RolesAllowed(value = { "USER", "ADMIN" })
|
||||
public String logOut(@Context final SecurityContext sc, @QueryParam("application") final String application)
|
||||
throws SystemException, InputException {
|
||||
LOGGER.debug("=====================================");
|
||||
LOGGER.debug("Get log_out()");
|
||||
LOGGER.debug("=====================================");
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.debug("== USER ? {}", gc.userByToken);
|
||||
|
||||
if (application == null) {
|
||||
throw new InputException("application", "Input error missing parameter");
|
||||
}
|
||||
String applicationName = application;
|
||||
boolean isDev = false;
|
||||
if (applicationName.endsWith("-dev")) {
|
||||
applicationName = applicationName.substring(0, applicationName.length() - 4);
|
||||
isDev = true;
|
||||
}
|
||||
LOGGER.debug("Search for '{}' base of '{}'", applicationName, application);
|
||||
|
||||
Application appl = null;
|
||||
try {
|
||||
appl = DataAccess.getWhere(Application.class,
|
||||
new Condition(new QueryCondition("name", "=", applicationName)));
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SystemException("Fail to log-Out...");
|
||||
}
|
||||
if (appl == null) {
|
||||
throw new SystemException("Authentiocate-wrong email/login '" + applicationName + "'");
|
||||
}
|
||||
String returnAdress = appl.redirect;
|
||||
if (isDev) {
|
||||
returnAdress = appl.redirectDev;
|
||||
}
|
||||
return returnAdress;
|
||||
}
|
||||
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.exception.DataAccessException;
|
||||
import org.kar.archidata.exception.InputException;
|
||||
import org.kar.karso.model.ApplicationToken;
|
||||
import org.kar.karso.model.CreateTokenRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/application_token")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class ApplicationTokenResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationTokenResource.class);
|
||||
|
||||
public ApplicationTokenResource() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic /application_token/{applicationId}
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@GET
|
||||
@Path("{applicationId}")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
public List<ApplicationToken> gets(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("applicationId") final Long applicationId) throws Exception {
|
||||
final List<ApplicationToken> values = DataAccess.getsWhere(ApplicationToken.class,
|
||||
new Condition(new QueryCondition("parentId", "=", applicationId)));
|
||||
// clean all tokens this is a secret:
|
||||
for (final ApplicationToken elem : values) {
|
||||
elem.token = null;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{applicationId}/{tokenId}")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
public void remove(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("applicationId") final Long applicationId,
|
||||
@PathParam("tokenId") final Integer tokenId) throws Exception {
|
||||
final long nbRemoved = DataAccess.deleteWhere(ApplicationToken.class,
|
||||
new Condition(new QueryAnd(new QueryCondition("parentId", "=", applicationId),
|
||||
new QueryCondition("id", "=", tokenId))));
|
||||
if (nbRemoved == 0) {
|
||||
throw new DataAccessException("Fail to remove token");
|
||||
}
|
||||
}
|
||||
|
||||
private String multipartCorrection(final String data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (data.contentEquals("null")) {
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static String randomToken() {
|
||||
final int len = 48;
|
||||
final String valid_element = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz0123456789#_@-~*!?";
|
||||
// creating a StringBuffer size of AlphaNumericStr
|
||||
final StringBuilder out = new StringBuilder(len);
|
||||
int iii;
|
||||
for (iii = 0; iii < len; iii++) {
|
||||
//generating a random number using math.random()
|
||||
final int ch = (int) (valid_element.length() * Math.random());
|
||||
//adding Random character one by one at the end of s
|
||||
out.append(valid_element.charAt(ch));
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{applicationId}/create")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public ApplicationToken create(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("applicationId") final Long applicationId,
|
||||
final CreateTokenRequest request) throws Exception {
|
||||
LOGGER.info("get user application TOKEN: app='{}' user='???'", applicationId);
|
||||
// correct input string stream :
|
||||
final String name = multipartCorrection(request.name);
|
||||
//validity = multipartCorrection(validity);
|
||||
LOGGER.debug("create a new token...");
|
||||
if (applicationId == null) {
|
||||
throw new InputException("applicationId", "can not be null");
|
||||
}
|
||||
final int maximum = 365 * 5;
|
||||
Integer validity = request.validity;
|
||||
if (validity == null || validity < 0 || validity > maximum) {
|
||||
validity = maximum;
|
||||
}
|
||||
LOGGER.warn("validity= {}", validity);
|
||||
// todo: set validity timestamp ...
|
||||
// TODO: check if application exist ...
|
||||
ApplicationToken token = new ApplicationToken();
|
||||
token.token = randomToken();
|
||||
token.name = multipartCorrection(name);
|
||||
token.parentId = applicationId;
|
||||
final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
|
||||
LOGGER.warn("Check Timestamp now = {}", now);
|
||||
token.endValidityTime = Timestamp.from(now.plusDays(validity).toInstant());
|
||||
LOGGER.warn("token.endValidityTime = {}", token.endValidityTime);
|
||||
|
||||
// insert in the BDD
|
||||
token = DataAccess.insert(token);
|
||||
// here we return the token to permit to the user to see it to set it in the application.
|
||||
return token;
|
||||
}
|
||||
/*
|
||||
Cannot find a deserializer for non-concrete Map type [map type; class jakarta.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]
|
||||
at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 1, column: 1]
|
||||
*/
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import org.kar.archidata.api.FrontGeneric;
|
||||
import org.kar.karso.util.ConfigVariable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
@Path("/front")
|
||||
public class Front extends FrontGeneric {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FrontGeneric.class);
|
||||
|
||||
public Front() {
|
||||
this.baseFrontFolder = ConfigVariable.getFrontFolder();
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import org.kar.archidata.exception.FailException;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/health_check")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class HealthCheck {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class);
|
||||
|
||||
public record HealthResult(
|
||||
String value) {};
|
||||
|
||||
@GET
|
||||
@PermitAll
|
||||
public HealthResult getHealth() throws FailException {
|
||||
if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) {
|
||||
throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token");
|
||||
}
|
||||
return new HealthResult("alive and kicking");
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.kar.archidata.tools.JWTWrapper.PublicKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.nimbusds.jose.JOSEException;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
@Path("/public_key")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class PublicKeyResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PublicKeyResource.class);
|
||||
|
||||
public PublicKeyResource() {
|
||||
|
||||
}
|
||||
|
||||
// This is for java server that use the same implementation
|
||||
// curl http://localhost:9993/public_key
|
||||
@GET
|
||||
@RolesAllowed(value = { "APPLICATION" })
|
||||
public PublicKey getKey() {
|
||||
return new PublicKey(JWTWrapper.getPublicKeyJson());
|
||||
}
|
||||
|
||||
// This is for common other interface that support public PEM stream.
|
||||
// curl http://localhost:9993/public_key/pem
|
||||
@GET
|
||||
@Path("/pem")
|
||||
@RolesAllowed(value = { "APPLICATION" })
|
||||
public String getKeyPem() throws JOSEException {
|
||||
final RSAPublicKey keyPub = JWTWrapper.getPublicKeyJava();
|
||||
final byte[] data = keyPub.getEncoded();
|
||||
final String base64encoded = new String(Base64.getEncoder().encode(data));
|
||||
return "-----BEGIN PUBLIC KEY-----\n" + base64encoded + "\n-----END PUBLIC KEY-----\n";
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.karso.model.Right;
|
||||
import org.kar.karso.model.RightDescription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
@Path("/right")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class RightResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RightResource.class);
|
||||
|
||||
public static List<RightDescription> getApplicationRightDecription(final long applicationId) throws Exception {
|
||||
return DataAccess.getsWhere(RightDescription.class,
|
||||
new Condition(new QueryCondition("applicationId", "=", applicationId)));
|
||||
}
|
||||
|
||||
public static List<Right> getRawUserRight(final long userId, final long applicationId) throws Exception {
|
||||
// Formatter:off
|
||||
return DataAccess.getsWhere(Right.class,
|
||||
new Condition(new QueryAnd(new QueryCondition("applicationId", "=", applicationId),
|
||||
new QueryCondition("userId", "=", userId))));
|
||||
// Formatter:on
|
||||
}
|
||||
|
||||
public static Map<String, PartRight> getUserRight(final long userId, final long applicationId) throws Exception {
|
||||
final Map<String, PartRight> out = new HashMap<>();
|
||||
final List<RightDescription> rightsDescriptions = getApplicationRightDecription(applicationId);
|
||||
LOGGER.trace("Get some descriptions: {} applicationId={}", rightsDescriptions.size(), applicationId);
|
||||
if (rightsDescriptions != null && rightsDescriptions.size() != 0) {
|
||||
final List<Right> rights = getRawUserRight(userId, applicationId);
|
||||
LOGGER.trace("Get some user right: count={} userID={} applicationId={}", rights.size(), userId,
|
||||
applicationId);
|
||||
LOGGER.trace("Rights:");
|
||||
for (final Right elem : rights) {
|
||||
LOGGER.trace(" - applId={} rightDescriptionId={} value={}", elem.applicationId,
|
||||
elem.rightDescriptionId, elem.value);
|
||||
}
|
||||
LOGGER.trace("RightDescription:");
|
||||
for (final RightDescription description : rightsDescriptions) {
|
||||
if (description == null) {
|
||||
continue;
|
||||
}
|
||||
LOGGER.trace(" - id={} key={}", description.id, description.key);
|
||||
}
|
||||
for (final RightDescription description : rightsDescriptions) {
|
||||
if (description == null) {
|
||||
continue;
|
||||
}
|
||||
final Right right = rights.stream().filter(elem -> elem.rightDescriptionId.equals(description.id))
|
||||
.findAny().orElse(null);
|
||||
if (right != null) {
|
||||
out.put(description.key, right.value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the application does not manage right with Karso (normal use-case)
|
||||
LOGGER.debug("Does not manage Karso right...");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static void updateUserRight(final long userId, final long applicationId, final Map<String, PartRight> delta)
|
||||
throws Exception {
|
||||
final List<RightDescription> rightsDescriptions = getApplicationRightDecription(applicationId);
|
||||
LOGGER.debug("Get some descriptions: {} applicationId={}", rightsDescriptions.size(), applicationId);
|
||||
if (rightsDescriptions == null || rightsDescriptions.size() == 0) {
|
||||
throw new IllegalArgumentException("Request change right on an application that does not manage any right");
|
||||
}
|
||||
final List<Right> rights = getRawUserRight(userId, applicationId);
|
||||
LOGGER.debug("Get some user right: count={} userID={}", rights.size(), userId);
|
||||
for (final RightDescription description : rightsDescriptions) {
|
||||
if (description == null) {
|
||||
// TODO: this is a really strange case to manage later...
|
||||
continue;
|
||||
}
|
||||
final PartRight newValue = delta.get(description.key);
|
||||
if (newValue == null) {
|
||||
//No need to update or create...
|
||||
continue;
|
||||
}
|
||||
final List<Right> allRights = rights.stream().filter(elem -> elem.rightDescriptionId.equals(description.id))
|
||||
.toList();
|
||||
if (allRights.size() > 1) {
|
||||
// special case of error somewhere else ... ==> remove all elements (except the first)
|
||||
for (int iii = 1; iii < allRights.size(); iii++) {
|
||||
LOGGER.error("Remove starnge element in Right id={} ", allRights.get(iii).id);
|
||||
DataAccess.delete(Right.class, allRights.get(iii).id);
|
||||
}
|
||||
}
|
||||
if (allRights.size() == 1) {
|
||||
final Right right = allRights.get(0);
|
||||
// The value exist, we need to update it
|
||||
LOGGER.debug("Request update a knonwn parameter: {} with {}", description.key, newValue);
|
||||
right.value = newValue;
|
||||
// TODO: maybe need to remove the value instead of set a new one ...
|
||||
DataAccess.update(right, right.id, List.of("value"));
|
||||
} else {
|
||||
// we need to create it
|
||||
LOGGER.debug("Request create parameter: {} with {}", description.key, newValue);
|
||||
final Right right = new Right();
|
||||
right.applicationId = applicationId;
|
||||
right.userId = userId;
|
||||
right.rightDescriptionId = description.id;
|
||||
right.value = newValue;
|
||||
DataAccess.insert(right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("ADMIN")
|
||||
public List<Right> gets() throws Exception {
|
||||
return DataAccess.gets(Right.class);
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Right post(final Right request) throws Exception {
|
||||
return DataAccess.insert(request);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public static Right get(@PathParam("id") final Long id) throws Exception {
|
||||
return DataAccess.get(Right.class, id);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Right patch(@PathParam("id") final Long id, @AsyncType(Right.class) final String jsonRequest)
|
||||
throws Exception {
|
||||
DataAccess.updateWithJson(Right.class, id, jsonRequest);
|
||||
return DataAccess.get(Right.class, id);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("ADMIN")
|
||||
public void remove(@PathParam("id") final Long id) throws Exception {
|
||||
DataAccess.delete(Right.class, id);
|
||||
}
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.exception.NotFoundException;
|
||||
import org.kar.karso.model.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/system_config")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class SystemConfigResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SystemConfigResource.class);
|
||||
|
||||
public static class GetSignUpAvailable {
|
||||
public boolean signup;
|
||||
|
||||
public GetSignUpAvailable(final boolean availlable) {
|
||||
this.signup = availlable;
|
||||
}
|
||||
|
||||
public GetSignUpAvailable() {
|
||||
this.signup = false;
|
||||
}
|
||||
}
|
||||
|
||||
public SystemConfigResource() {}
|
||||
|
||||
@GET
|
||||
@Path("is_sign_up_availlable")
|
||||
@PermitAll
|
||||
public GetSignUpAvailable isSignUpAvailable() throws Exception {
|
||||
final Settings set = DataAccess.getWhere(Settings.class,
|
||||
new Condition(new QueryCondition("key", "=", "SIGN_UP_ENABLE")));
|
||||
if (set == null) {
|
||||
throw new NotFoundException("Value does not exist");
|
||||
}
|
||||
final boolean availlable = "true".equalsIgnoreCase(set.value);
|
||||
final GetSignUpAvailable tmp = new GetSignUpAvailable(availlable);
|
||||
LOGGER.debug("mlkmlk {}", tmp.signup);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("key/{key}")
|
||||
@RolesAllowed(value = { "USER", "ADMIN" })
|
||||
public Map<String, Object> getKey(@Context final SecurityContext sc, @PathParam("key") final String key)
|
||||
throws Exception {
|
||||
final Settings set = DataAccess.getWhere(Settings.class, new Condition(new QueryCondition("key", "=", key)));
|
||||
if (set == null) {
|
||||
throw new NotFoundException("Value does not exist");
|
||||
}
|
||||
final Map<String, Object> out = new HashMap<>();
|
||||
if ("BOOLEAN".equals(set.type)) {
|
||||
final boolean available = "true".equalsIgnoreCase(set.value);
|
||||
out.put("value", available);
|
||||
} else if ("NUMBER".equals(set.type)) {
|
||||
final double value = Double.parseDouble(set.value);
|
||||
out.put("value", value);
|
||||
} else {
|
||||
out.put("value", set.value);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("key/{key}")
|
||||
@RolesAllowed(value = { "ADMIN" })
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void setKey(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("key") final String key,
|
||||
@AsyncType(Object.class) final String jsonRequest) throws Exception {
|
||||
Settings res = null;
|
||||
try {
|
||||
res = DataAccess.getWhere(Settings.class, new Condition(new QueryCondition("key", "=", key)));
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
final String result = "Can not find the Key: '" + key + "'";
|
||||
throw new NotFoundException(result);
|
||||
}
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
// Read the tree to filter injection of data:
|
||||
final JsonNode root = mapper.readTree(jsonRequest);
|
||||
final JsonNode value = root.findPath("value");
|
||||
|
||||
res.value = value.asText();
|
||||
LOGGER.debug("Update value : {}", res.value);
|
||||
DataAccess.update(res, res.id, List.of("value"));
|
||||
}
|
||||
|
||||
}
|
@ -1,374 +0,0 @@
|
||||
package org.kar.karso.api;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.dataAccess.options.ReadAllColumn;
|
||||
import org.kar.archidata.exception.FailException;
|
||||
import org.kar.archidata.exception.SystemException;
|
||||
import org.kar.archidata.filter.GenericContext;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.model.GetToken;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.kar.karso.migration.Initialization;
|
||||
import org.kar.karso.model.Application;
|
||||
import org.kar.karso.model.ChangePassword;
|
||||
import org.kar.karso.model.ChangePassword.ChangePasswordChecker;
|
||||
import org.kar.karso.model.DataGetToken;
|
||||
import org.kar.karso.model.DataGetToken.DataGetTokenChecker;
|
||||
import org.kar.karso.model.Right;
|
||||
import org.kar.karso.model.RightDescription;
|
||||
import org.kar.karso.model.UserAuth;
|
||||
import org.kar.karso.model.UserAuth.UserAuthChecker;
|
||||
import org.kar.karso.model.UserAuthGet;
|
||||
import org.kar.karso.model.UserCreate;
|
||||
import org.kar.karso.model.UserCreate.UserCreateChecker;
|
||||
import org.kar.karso.util.ConfigVariable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
@Path("/users")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class UserResource {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
|
||||
static final UserAuthChecker CHECKER = new UserAuthChecker();
|
||||
static final DataGetTokenChecker CHECKER_REQUEST_TOKEN = new DataGetTokenChecker();
|
||||
static final ChangePasswordChecker CHECKER_CHANGE_PASSWORD = new ChangePasswordChecker();
|
||||
static final UserCreateChecker CHECKER_CREATE_USER = new UserCreateChecker();
|
||||
public static final String APPLICATION = "karso";
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class UserOut {
|
||||
public long id;
|
||||
public String login;
|
||||
|
||||
public UserOut(final long id, final String login) {
|
||||
this.id = id;
|
||||
this.login = login;
|
||||
}
|
||||
}
|
||||
|
||||
public UserResource() {}
|
||||
|
||||
@GET
|
||||
@RolesAllowed("ADMIN")
|
||||
public List<UserAuthGet> gets() throws Exception {
|
||||
final List<UserAuthGet> out = DataAccess.gets(UserAuthGet.class);
|
||||
return out;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@RolesAllowed({ "ADMIN", "USER" })
|
||||
public UserAuthGet get(@Context final SecurityContext sc, @PathParam("id") final long id) throws Exception {
|
||||
if (!sc.isUserInRole("ADMIN")) {
|
||||
// in case of user we need to check if it get his own id parameters:
|
||||
final UserAuthGet ret = DataAccess.get(UserAuthGet.class, id, new AccessDeletedItems());
|
||||
return ret;
|
||||
}
|
||||
final UserAuthGet ret = DataAccess.get(UserAuthGet.class, id);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
// Find element in deleted
|
||||
return DataAccess.get(UserAuthGet.class, id, new AccessDeletedItems(), new ReadAllColumn());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{userId}/application/{applicationId}/link")
|
||||
@RolesAllowed("ADMIN")
|
||||
public UserAuth linkApplication(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("userId") final long userId,
|
||||
@PathParam("applicationId") final long applicationId,
|
||||
final boolean data) throws Exception {
|
||||
LOGGER.debug("Find typeNode");
|
||||
try (DBAccess db = DBAccess.createInterface()) {
|
||||
if (data) {
|
||||
AddOnManyToMany.addLink(db, UserAuth.class, userId, "application", applicationId);
|
||||
} else {
|
||||
AddOnManyToMany.removeLink(db, UserAuth.class, userId, "application", applicationId);
|
||||
}
|
||||
return db.get(UserAuth.class, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{userId}/application/{applicationId}/rights")
|
||||
@RolesAllowed("ADMIN")
|
||||
public Map<String, PartRight> getApplicationRight(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("userId") final long userId,
|
||||
@PathParam("applicationId") final long applicationId) throws Exception {
|
||||
return RightResource.getUserRight(userId, applicationId);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("{userId}/application/{applicationId}/rights")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Map<String, PartRight> patchApplicationRight(
|
||||
@Context final SecurityContext sc,
|
||||
@PathParam("userId") final long userId,
|
||||
@PathParam("applicationId") final long applicationId,
|
||||
final Map<String, PartRight> data) throws Exception {
|
||||
this.LOGGER.info("Patch data from FRONT: {}", data);
|
||||
RightResource.updateUserRight(userId, applicationId, data);
|
||||
return RightResource.getUserRight(userId, applicationId);
|
||||
}
|
||||
|
||||
// TODO: check this it might be deprecated ...
|
||||
@POST
|
||||
@Path("{id}/set_admin")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void setAdmin(@Context final SecurityContext sc, @PathParam("id") final long userId, final boolean data)
|
||||
throws Exception {
|
||||
try (DBAccess da = DBAccess.createInterface()) {
|
||||
final Application appKarso = da.get(Application.class,
|
||||
new Condition(new QueryCondition("name", "=", UserResource.APPLICATION)));
|
||||
final RightDescription rightsDescription = da.get(RightDescription.class,
|
||||
new Condition(new QueryAnd(new QueryCondition("key", "=", "ADMIN"),
|
||||
new QueryCondition("applicationId", "=", appKarso.id))));
|
||||
|
||||
final Right right = da.get(Right.class,
|
||||
new Condition(new QueryAnd(new QueryCondition("rightDescriptionId", "=", rightsDescription.id),
|
||||
new QueryCondition("applicationId", "=", appKarso.id),
|
||||
new QueryCondition("userId", "=", userId))));
|
||||
if (right == null) {
|
||||
final Right newRight = new Right();
|
||||
newRight.applicationId = appKarso.id;
|
||||
newRight.userId = userId;
|
||||
newRight.rightDescriptionId = rightsDescription.id;
|
||||
newRight.value = PartRight.READ_WRITE;
|
||||
da.insert(newRight);
|
||||
return;
|
||||
} else if (PartRight.READ_WRITE.equals(right.value)) {
|
||||
return;
|
||||
}
|
||||
// TODO: maybe remove ???
|
||||
right.value = PartRight.READ_WRITE;
|
||||
final long ret = da.update(right, right.id, List.of("value"));
|
||||
if (ret == 0) {
|
||||
throw new FailException(Response.Status.NOT_MODIFIED, "Fail to modify user as an admin.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/set_blocked")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void setBlocked(@Context final SecurityContext sc, @PathParam("id") final long userId, final boolean data)
|
||||
throws Exception {
|
||||
final UserAuth user = new UserAuth();
|
||||
user.blocked = data;
|
||||
final long ret = DataAccess.update(user, userId, List.of("blocked"));
|
||||
if (ret == 0) {
|
||||
throw new FailException(Response.Status.NOT_MODIFIED, "Fail to block the User.");
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public UserAuthGet create(final UserCreate user) throws Exception {
|
||||
LOGGER.debug("create new User email={} login={}", user.email, user.login);
|
||||
try (DBAccess da = DBAccess.createInterface()) {
|
||||
CHECKER_CREATE_USER.checkAll(da, "", user, null);
|
||||
// Check login does not exist
|
||||
List<UserAuth> out = da.getsWhere(UserAuth.class,
|
||||
new Condition(new QueryCondition("login", "=", user.login)));
|
||||
if (out.size() >= 1) {
|
||||
throw new FailException(Response.Status.BAD_REQUEST, "Login already used !!!");
|
||||
}
|
||||
// Check email does not exist
|
||||
out = da.getsWhere(UserAuth.class, new Condition(new QueryCondition("email", "=", user.email)));
|
||||
if (out.size() >= 1) {
|
||||
throw new FailException(Response.Status.BAD_REQUEST, "e-mail already used !!!");
|
||||
}
|
||||
// Add new user and return formated data.
|
||||
final UserAuth newUser = new UserAuth();
|
||||
newUser.blocked = false;
|
||||
newUser.avatar = false;
|
||||
newUser.login = user.login;
|
||||
newUser.password = user.password;
|
||||
newUser.email = user.email;
|
||||
newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now());
|
||||
final UserAuth tmp = da.insert(newUser);
|
||||
LOGGER.debug("create new user done with id=={}", tmp.id);
|
||||
return da.get(UserAuthGet.class, tmp.id);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("me")
|
||||
@RolesAllowed("USER")
|
||||
public UserOut getMe(@Context final SecurityContext sc) {
|
||||
LOGGER.debug("getMe()");
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.debug("== USER ? {}", gc.userByToken);
|
||||
return new UserOut(gc.userByToken.id, gc.userByToken.name);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("password")
|
||||
@RolesAllowed("USER")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void changePassword(@Context final SecurityContext sc, final ChangePassword data) throws Exception {
|
||||
LOGGER.debug("ChangePassword()");
|
||||
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
LOGGER.debug("== USER ? {}", gc.userByToken);
|
||||
try (DBAccess da = DBAccess.createInterface()) {
|
||||
CHECKER_CHANGE_PASSWORD.checkAll(da, "", data, null);
|
||||
final UserAuth user = checkAuthUser(data.login, data.time, data.password);
|
||||
if (user == null) {
|
||||
throw new SystemException("Fail to retrieve the user... (impossible case)");
|
||||
}
|
||||
if (!user.id.equals(gc.userByToken.id)) {
|
||||
throw new SystemException("Try to change the password of an other user !!! You are BAD...");
|
||||
}
|
||||
// Process the update:
|
||||
user.password = data.newPassword;
|
||||
DataAccess.update(user, user.id, List.of("password"));
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("is_login_exist")
|
||||
@PermitAll
|
||||
public Boolean isLoginExist(@QueryParam("login") final String login) throws Exception {
|
||||
LOGGER.debug("checkLogin: '{}'", login);
|
||||
final List<UserAuth> out = DataAccess.getsWhere(UserAuth.class,
|
||||
new Condition(new QueryCondition("login", "=", login)));
|
||||
return out.size() >= 1;
|
||||
}
|
||||
|
||||
// TODO: add an application TOKEN and permit only 50 requested (maybe add an option to disable it).
|
||||
@GET
|
||||
@Path("is_email_exist")
|
||||
@PermitAll
|
||||
public Boolean isEmailExist(@QueryParam("email") final String email) throws Exception {
|
||||
LOGGER.debug("checkEmail: {}", email);
|
||||
final List<UserAuth> out = DataAccess.getsWhere(UserAuth.class,
|
||||
new Condition(new QueryCondition("email", "=", email)));
|
||||
return out.size() >= 1;
|
||||
}
|
||||
|
||||
private UserAuth checkAuthUser(final String login, final String time, final String password) throws Exception {
|
||||
// email or login?
|
||||
String query = "login";
|
||||
if (login.contains("@")) {
|
||||
query = "email";
|
||||
}
|
||||
final UserAuth user = DataAccess.getWhere(UserAuth.class, new Condition(new QueryCondition(query, "=", login)),
|
||||
new AccessDeletedItems(), new ReadAllColumn());
|
||||
|
||||
if (user == null) {
|
||||
throw new FailException(Response.Status.PRECONDITION_FAILED,
|
||||
"FAIL Authenticate-wrong email/login '" + login + "')");
|
||||
}
|
||||
// Check the password:
|
||||
final String passwordCheck = getSHA512(
|
||||
"login='" + login + "';pass='" + user.password + "';date='" + time + "'");
|
||||
if (!passwordCheck.contentEquals(password)) {
|
||||
throw new FailException(Response.Status.PRECONDITION_FAILED, "Password error ...");
|
||||
}
|
||||
LOGGER.debug(" ==> pass nearly all test: blocked={} deleted={} ", user.blocked, user.deleted);
|
||||
if (user.blocked || (user.deleted != null && user.deleted == true)) {
|
||||
throw new FailException(Response.Status.UNAUTHORIZED, "FAIL Authentiocate");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("get_token")
|
||||
@PermitAll
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public GetToken getToken(final DataGetToken data) throws Exception {
|
||||
LOGGER.info("User Authenticate: {}", data.login);
|
||||
try (DBAccess da = DBAccess.createInterface()) {
|
||||
CHECKER_REQUEST_TOKEN.checkAll(da, "", data, null);
|
||||
final UserAuth user = checkAuthUser(data.login, data.time, data.password);
|
||||
// at the point the user has been not deleted and not blocked.
|
||||
// this authentication is valid only for Karso ==> not for the application
|
||||
final int expirationTimeInMinutes = ConfigVariable.getAuthExpirationTime();
|
||||
// Get the USER Right (Note: by construction KARSO have application ID = KARSO_INITIALISATION_ID
|
||||
final Map<String, PartRight> ssoRight = RightResource.getUserRight(user.id,
|
||||
Initialization.KARSO_INITIALISATION_ID);
|
||||
if (!ssoRight.containsKey("USER")) {
|
||||
// If the USER is not override, the system add by default USER
|
||||
ssoRight.put("USER", PartRight.READ_WRITE);
|
||||
}
|
||||
final Map<String, Integer> rightForFront = new HashMap<>();
|
||||
for (final Map.Entry<String, PartRight> entry : ssoRight.entrySet()) {
|
||||
rightForFront.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
LOGGER.debug("Get new token with right: {}", ssoRight);
|
||||
final Map<String, Object> outRight = new HashMap<>();
|
||||
// we set the right in the under map to manage multiple application group right. and in some application user can see other user or all user of the application
|
||||
outRight.put(UserResource.APPLICATION, rightForFront);
|
||||
// TODO: maybe correct this get of TTL...
|
||||
final String ret = JWTWrapper.generateJWToken(user.id, user.login, "KarAuth", UserResource.APPLICATION,
|
||||
outRight, expirationTimeInMinutes);
|
||||
if (ret == null) {
|
||||
throw new SystemException("Missing internal JWT system ==> can not sign anything ...");
|
||||
}
|
||||
// Update last connection:
|
||||
final UserAuth newUser = new UserAuth();
|
||||
newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now());
|
||||
da.update(newUser, user.id, List.of("lastConnection"));
|
||||
return new GetToken(ret);
|
||||
}
|
||||
}
|
||||
|
||||
public static String bytesToHex(final byte[] bytes) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final byte b : bytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getSHA512(final String passwordToHash) {
|
||||
try {
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
final byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
|
||||
return bytesToHex(bytes);
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package org.kar.karso.filter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.filter.AuthenticationFilter;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.model.UserByToken;
|
||||
import org.kar.karso.api.UserResource;
|
||||
import org.kar.karso.model.ApplicationToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.ws.rs.Priorities;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
//@PreMatching
|
||||
@Provider
|
||||
@Priority(Priorities.AUTHENTICATION)
|
||||
public class KarsoAuthenticationFilter extends AuthenticationFilter {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KarsoAuthenticationFilter.class);
|
||||
|
||||
//curl http://0.0.0.0:15080/karso/api/public_key/pem --output plop.txt -H "Authorization: Zota 1:U0sJM1m@-STSdfg4365fJOFUGbR4kFycBu1qGZPwf7gW6k2WWRBzTPUH7QutCgPw-SDss45_563sSDFdfg@dsf@456" --verbose
|
||||
|
||||
public KarsoAuthenticationFilter() {
|
||||
super(UserResource.APPLICATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserByToken validateToken(final String authorization) throws Exception {
|
||||
if (authorization == null || authorization.length() < 25) {
|
||||
System.out.println("Application authentication too short '" + authorization + "'");
|
||||
return null;
|
||||
}
|
||||
final String[] elems = authorization.split(":");
|
||||
if (elems.length != 2) {
|
||||
System.out.println("Application authentication split error '" + authorization + "'");
|
||||
return null;
|
||||
}
|
||||
final Long indexToken = Long.parseLong(elems[0]);
|
||||
|
||||
final ApplicationToken value = DataAccess.get(ApplicationToken.class, indexToken);
|
||||
if (value == null) {
|
||||
System.out.println("Application authentication can not find id '" + authorization + "'");
|
||||
return null;
|
||||
}
|
||||
// TODO: hash the sent token
|
||||
if (!value.token.equals(elems[1])) {
|
||||
System.out.println("Application authentication mismatch '" + authorization + "'");
|
||||
return null;
|
||||
}
|
||||
// TODO: check UTC !!!
|
||||
if (!value.endValidityTime.after(Timestamp.from(Instant.now()))) {
|
||||
System.out.println("Application authentication Time-out '" + authorization + "' " + value.endValidityTime
|
||||
+ " > " + Timestamp.from(Instant.now()));
|
||||
return null;
|
||||
}
|
||||
// ----------------------------------
|
||||
// -- All is good !!!
|
||||
// ----------------------------------
|
||||
// We are in transition phase the user element will be removed
|
||||
final UserByToken userByToken = new UserByToken();
|
||||
userByToken.id = value.id;
|
||||
userByToken.name = value.name;
|
||||
userByToken.parentId = value.parentId;
|
||||
userByToken.type = UserByToken.TYPE_APPLICATION;
|
||||
// TODO: Manage the retrieve of specific rights ...
|
||||
userByToken.right.put(UserResource.APPLICATION, Map.of("APPLICATION", PartRight.READ_WRITE));
|
||||
return userByToken;
|
||||
}
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
package org.kar.karso.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.api.DataResource;
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
|
||||
import org.kar.archidata.externalRestApi.AnalyzeApi;
|
||||
import org.kar.archidata.externalRestApi.TsGenerateApi;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.model.token.JwtToken;
|
||||
import org.kar.karso.api.ApplicationResource;
|
||||
import org.kar.karso.api.ApplicationTokenResource;
|
||||
import org.kar.karso.api.Front;
|
||||
import org.kar.karso.api.PublicKeyResource;
|
||||
import org.kar.karso.api.RightResource;
|
||||
import org.kar.karso.api.SystemConfigResource;
|
||||
import org.kar.karso.api.UserResource;
|
||||
import org.kar.karso.model.Application;
|
||||
import org.kar.karso.model.ApplicationToken;
|
||||
import org.kar.karso.model.Right;
|
||||
import org.kar.karso.model.RightDescription;
|
||||
import org.kar.karso.model.Settings;
|
||||
import org.kar.karso.model.UserAuth;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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 List<Class<?>> CLASSES_BASE = List.of(Settings.class, UserAuth.class, Application.class,
|
||||
ApplicationToken.class, RightDescription.class, Right.class);
|
||||
|
||||
// created object
|
||||
private Application app = null;
|
||||
private UserAuth user = null;
|
||||
|
||||
private RightDescription rightDescription;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Initialization";
|
||||
}
|
||||
|
||||
public static void generateObjects() throws Exception {
|
||||
LOGGER.info("Generate APIs");
|
||||
final List<Class<?>> listOfResources = List.of(Front.class, DataResource.class, ApplicationResource.class,
|
||||
ApplicationTokenResource.class, PublicKeyResource.class, RightResource.class, UserResource.class,
|
||||
SystemConfigResource.class);
|
||||
final AnalyzeApi api = new AnalyzeApi();
|
||||
api.addAllApi(listOfResources);
|
||||
api.addModel(JwtToken.class);
|
||||
TsGenerateApi.generateApi(api, "../front/src/back-api/");
|
||||
LOGGER.info("Generate APIs (DONE)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() throws Exception {
|
||||
for (final Class<?> clazz : CLASSES_BASE) {
|
||||
addClass(clazz);
|
||||
}
|
||||
|
||||
addAction((final DBAccess da) -> {
|
||||
final Application app = new Application();
|
||||
//app.id = 1L;
|
||||
app.name = "karso";
|
||||
app.description = "Root SSO interface";
|
||||
app.redirect = "https://atria-soft.org/karso/sso";
|
||||
app.redirectDev = "http://localhost:4003/karso/sso";
|
||||
app.notification = "";
|
||||
app.ttl = 666;
|
||||
this.app = da.insert(app);
|
||||
});
|
||||
// default admin: "karadmin" password: "adminA@666"
|
||||
addAction((final DBAccess da) -> {
|
||||
final UserAuth user = new UserAuth();
|
||||
//user.id = 1L;
|
||||
user.login = "karadmin";
|
||||
user.password = UserResource.getSHA512("adminA@666");
|
||||
user.email = "admin@admin.ZZZ";
|
||||
this.user = da.insert(user);
|
||||
});
|
||||
addAction((final DBAccess da) -> {
|
||||
AddOnManyToMany.addLink(da, UserAuth.class, this.user.id, "application", this.app.id);
|
||||
});
|
||||
addAction((final DBAccess da) -> {
|
||||
final Settings settings = new Settings();
|
||||
settings.key = "SIGN_UP_ENABLE";
|
||||
settings.right = "rwr-r-";
|
||||
settings.type = "BOOLEAN";
|
||||
settings.value = "false";
|
||||
da.insert(settings);
|
||||
settings.key = "SIGN_IN_ENABLE";
|
||||
settings.right = "rwr-r-";
|
||||
settings.type = "BOOLEAN";
|
||||
settings.value = "true";
|
||||
da.insert(settings);
|
||||
settings.key = "SIGN_UP_FILTER";
|
||||
settings.right = "rw----";
|
||||
settings.type = "STRING";
|
||||
settings.value = ".*";
|
||||
da.insert(settings);
|
||||
settings.key = "EMAIL_VALIDATION_REQUIRED";
|
||||
settings.right = "rwr-r-";
|
||||
settings.type = "BOOLEAN";
|
||||
settings.value = "false";
|
||||
da.insert(settings);
|
||||
});
|
||||
addAction((final DBAccess da) -> {
|
||||
final RightDescription rightDescription = new RightDescription();
|
||||
rightDescription.applicationId = this.app.id;
|
||||
rightDescription.key = "ADMIN";
|
||||
rightDescription.title = "Administrator";
|
||||
rightDescription.description = "Full administrator Right";
|
||||
this.rightDescription = da.insert(rightDescription);
|
||||
});
|
||||
addAction((final DBAccess da) -> {
|
||||
final Right right = new Right();
|
||||
right.applicationId = this.app.id;
|
||||
right.userId = this.user.id;
|
||||
right.rightDescriptionId = this.rightDescription.id;
|
||||
right.value = PartRight.READ_WRITE;
|
||||
da.insert(right);
|
||||
});
|
||||
// we generate an offset to permit to manage some generic upgrade in the future...
|
||||
addAction("""
|
||||
ALTER TABLE `application` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
addAction("""
|
||||
ALTER TABLE `user` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
addAction("""
|
||||
ALTER TABLE `settings` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
addAction("""
|
||||
ALTER TABLE `right` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
addAction("""
|
||||
ALTER TABLE `rightDescription` AUTO_INCREMENT = 1000;
|
||||
""", "mysql");
|
||||
display();
|
||||
}
|
||||
|
||||
public static void dropAll(final DBAccess da) {
|
||||
for (final Class<?> element : CLASSES_BASE) {
|
||||
try {
|
||||
da.drop(element);
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Fail to drop table !!!!!!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanAll(final DBAccess da) {
|
||||
for (final Class<?> element : CLASSES_BASE) {
|
||||
try {
|
||||
da.cleanAll(element);
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Fail to clean table !!!!!!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package org.kar.karso.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
|
||||
public class Migration20231015 extends MigrationSqlStep {
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "refactor creation and update time";
|
||||
}
|
||||
|
||||
public Migration20231015() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() {
|
||||
|
||||
for (final String elem : List.of("application", "applicationToken", "right", "rightDescription", "settings",
|
||||
"user", "user_link_application")) { //, "user_link_cover")) {
|
||||
|
||||
addAction("""
|
||||
ALTER TABLE `""" + elem + """
|
||||
`
|
||||
RENAME COLUMN `create_date` TO `createdAt`,
|
||||
RENAME COLUMN `modify_date` TO `updatedAt`;
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
package org.kar.karso.migration;
|
||||
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
|
||||
public class Migration20231126 extends MigrationSqlStep {
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "migration-2023-11-26: reorder the migration for the new API of archidata";
|
||||
}
|
||||
|
||||
public Migration20231126() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() {
|
||||
// update migration update (last one)
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `KAR_migration`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
ADD `version` int NOT NULL DEFAULT '2' AFTER `deleted`,
|
||||
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'Name of the migration' AFTER `version`,
|
||||
CHANGE `terminated` `terminated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'if the migration is well terminated or not' AFTER `name`,
|
||||
CHANGE `stepId` `stepId` int NULL COMMENT 'index in the migration progression' AFTER `terminated`,
|
||||
CHANGE `count` `count` int NULL COMMENT 'number of element in the migration' AFTER `stepId`,
|
||||
CHANGE `log` `log` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Log generate by the migration' AFTER `count`;
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `application`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
|
||||
CHANGE `description` `description` varchar(2048) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `name`,
|
||||
CHANGE `redirect` `redirect` varchar(2048) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL AFTER `description`,
|
||||
CHANGE `redirectDev` `redirectDev` varchar(2048) COLLATE 'utf8mb4_0900_ai_ci' NULL DEFAULT 'http://localhost:4200/sso/' AFTER `redirect`,
|
||||
CHANGE `notification` `notification` varchar(2048) COLLATE 'utf8mb4_0900_ai_ci' NULL DEFAULT 'http://localhost:4200/sso/notification' AFTER `redirectDev`,
|
||||
CHANGE `ttl` `ttl` int NOT NULL DEFAULT '666' COMMENT 'Expiration time ' AFTER `notification`,
|
||||
CHANGE `manageRight` `manageRight` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Right is manage with Karso' AFTER `ttl`;
|
||||
""");
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `applicationToken`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `parentId` `parentId` bigint NOT NULL AFTER `deleted`,
|
||||
CHANGE `name` `name` text COLLATE 'utf8mb3_general_ci' NOT NULL AFTER `parentId`,
|
||||
CHANGE `endValidityTime` `endValidityTime` timestamp(3) NOT NULL AFTER `name`,
|
||||
CHANGE `token` `token` text COLLATE 'utf8mb3_general_ci' NOT NULL AFTER `endValidityTime`;
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `right`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `applicationId` `applicationId` bigint NOT NULL COMMENT 'application-ID that have the reference of the right' AFTER `deleted`,
|
||||
CHANGE `userId` `userId` bigint NOT NULL COMMENT 'user-ID ' AFTER `applicationId`,
|
||||
CHANGE `rightDescriptionId` `rightDescriptionId` bigint NOT NULL COMMENT 'rightDescription-ID of the right description' AFTER `userId`,
|
||||
CHANGE `value` `value` varchar(1024) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Value of the right' AFTER `rightDescriptionId`;
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `rightDescription`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `applicationId` `applicationId` bigint NOT NULL COMMENT 'Application id that have the reference of the right' AFTER `deleted`,
|
||||
CHANGE `key` `key` varchar(64) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Key of the property' AFTER `applicationId`,
|
||||
CHANGE `title` `title` varchar(1024) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Title of the right' AFTER `key`,
|
||||
CHANGE `description` `description` varchar(1024) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Description of the right' AFTER `title`,
|
||||
CHANGE `defaultValue` `defaultValue` varchar(1024) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'default value if Never set' AFTER `description`,
|
||||
CHANGE `type` `type` varchar(16) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL DEFAULT 'BOOLEAN' COMMENT 'Type of the property' AFTER `defaultValue`;
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `settings`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `key` `key` varchar(512) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL AFTER `deleted`,
|
||||
CHANGE `right` `right` varchar(6) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL DEFAULT 'rw----' COMMENT 'Right for the specific element(ADMIN [rw] USER [rw] other [rw])' AFTER `key`,
|
||||
CHANGE `type` `type` varchar(10) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Type Of the data' AFTER `right`,
|
||||
CHANGE `value` `value` text COLLATE 'utf8mb3_general_ci' NOT NULL COMMENT 'Value of the configuration' AFTER `type`;
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
ALTER TABLE `user`
|
||||
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
|
||||
CHANGE `login` `login` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
|
||||
CHANGE `lastConnection` `lastConnection` timestamp(3) NULL AFTER `login`,
|
||||
CHANGE `admin` `admin` tinyint(1) NOT NULL DEFAULT '0' AFTER `lastConnection`,
|
||||
CHANGE `blocked` `blocked` tinyint(1) NOT NULL DEFAULT '0' AFTER `admin`,
|
||||
CHANGE `removed` `removed` tinyint(1) NOT NULL DEFAULT '0' AFTER `blocked`,
|
||||
CHANGE `password` `password` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL AFTER `removed`,
|
||||
CHANGE `email` `email` varchar(512) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL AFTER `password`,
|
||||
CHANGE `emailValidate` `emailValidate` timestamp(3) NULL AFTER `email`,
|
||||
CHANGE `newEmail` `newEmail` varchar(512) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `emailValidate`,
|
||||
CHANGE `avatar` `avatar` tinyint(1) NOT NULL DEFAULT '0' AFTER `newEmail`;
|
||||
""");
|
||||
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
|
||||
CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
|
||||
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
|
||||
CHANGE `user_id` `object1id` bigint NOT NULL AFTER `deleted`,
|
||||
CHANGE `application_id` `object2id` bigint NOT NULL AFTER `object1id`,
|
||||
ADD FOREIGN KEY (`object1id`) REFERENCES `user` (`id`);
|
||||
""");
|
||||
|
||||
addAction(
|
||||
"""
|
||||
CREATE TABLE `user_link_cover` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key of the base' ,
|
||||
`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' ,
|
||||
`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'When update the object' ,
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' ,
|
||||
`object1Id` bigint NOT NULL COMMENT 'Object reference 1' ,
|
||||
`object2Id` bigint NOT NULL COMMENT 'Object reference 2' ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
""");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package org.kar.karso.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.kar.archidata.dataAccess.options.OverrideTableName;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.archidata.tools.UuidUtils;
|
||||
import org.kar.karso.migration.model.UUIDConversion;
|
||||
|
||||
public class Migration20240515 extends MigrationSqlStep {
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "migration-2024-05-15: Update the link user application and the cover";
|
||||
}
|
||||
|
||||
public Migration20240515() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() {
|
||||
// update migration update (last one)
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application` ADD `uuid` binary(16) AFTER `id`;
|
||||
""");
|
||||
addAction((final DBAccess da) -> {
|
||||
final List<UUIDConversion> datas = da.gets(UUIDConversion.class, new AccessDeletedItems(),
|
||||
new OverrideTableName("user_link_application"));
|
||||
for (final UUIDConversion elem : datas) {
|
||||
elem.uuid = UuidUtils.nextUUID();
|
||||
}
|
||||
for (final UUIDConversion elem : datas) {
|
||||
da.update(elem, elem.id, List.of("uuid"), new OverrideTableName("user_link_application"));
|
||||
}
|
||||
});
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
CHANGE `id` `id` bigint;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application` DROP PRIMARY KEY;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
CHANGE `uuid` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
ADD PRIMARY KEY `uuid` (`uuid`);
|
||||
""");
|
||||
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
DROP `id`;
|
||||
""");
|
||||
|
||||
addAction("""
|
||||
DROP TABLE `user_link_cover`;
|
||||
""");
|
||||
|
||||
addAction("""
|
||||
ALTER TABLE `user`
|
||||
ADD `covers` json DEFAULT NULL COMMENT 'List of Id of the specific covers' AFTER `removed`;
|
||||
""");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package org.kar.karso.migration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
|
||||
import org.kar.archidata.dataAccess.options.OverrideTableName;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.migration.MigrationSqlStep;
|
||||
import org.kar.karso.migration.model.OIDConversion;
|
||||
import org.kar.karso.model.Right;
|
||||
|
||||
public class Migration20250204 extends MigrationSqlStep {
|
||||
|
||||
public static final int KARSO_INITIALISATION_ID = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "migration-2025-02-04: mograte native id as ObjectId";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateStep() {
|
||||
// update migration update (last one)
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application` ADD `_id` binary(12) AFTER `uuid`;
|
||||
""");
|
||||
addAction((final DBAccess da) -> {
|
||||
final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(),
|
||||
new OverrideTableName("user_link_application"));
|
||||
for (final OIDConversion elem : datas) {
|
||||
elem._id = new ObjectId();
|
||||
}
|
||||
for (final OIDConversion elem : datas) {
|
||||
da.update(elem, elem.uuid, List.of("_id"), new OverrideTableName("user_link_application"));
|
||||
}
|
||||
});
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
CHANGE `uuid` `uuid` binary(16);
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application` DROP PRIMARY KEY;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
CHANGE `_id` `_id` binary(12) NOT NULL;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
ADD PRIMARY KEY `_id` (`_id`);
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user_link_application`
|
||||
DROP `uuid`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user`
|
||||
DROP `admin`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user`
|
||||
DROP `removed`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `user` ADD `blockedReason` varchar(512) AFTER `blocked`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `right`
|
||||
DROP `value`;
|
||||
""");
|
||||
addAction("""
|
||||
ALTER TABLE `right` ADD `value` JSON NOT NULL AFTER `rightDescriptionId`;
|
||||
""");
|
||||
addAction((final DBAccess da) -> {
|
||||
final List<Right> datas = da.gets(Right.class, new AccessDeletedItems());
|
||||
for (final Right elem : datas) {
|
||||
elem.value = PartRight.READ_WRITE;
|
||||
}
|
||||
for (final Right elem : datas) {
|
||||
da.update(elem, elem.id, List.of("value"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package org.kar.karso.migration.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
public class OIDConversion {
|
||||
@Id
|
||||
public UUID uuid = null;
|
||||
public ObjectId _id = null;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.kar.karso.migration.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
public class UUIDConversion {
|
||||
@Id
|
||||
public Long id = null;
|
||||
public UUID uuid = null;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class AddUserData {
|
||||
public Long userId;
|
||||
|
||||
public AddUserData() {}
|
||||
|
||||
public AddUserData(final long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
|
||||
@Table(name = "application")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Application extends GenericDataSoftDelete {
|
||||
@Column(length = 256)
|
||||
public String name;
|
||||
@Column(length = 2048)
|
||||
public String description;
|
||||
@Column(length = 2048, nullable = false)
|
||||
public String redirect;
|
||||
@Column(length = 2048)
|
||||
@DefaultValue("'http://localhost:4200/sso/'")
|
||||
public String redirectDev;
|
||||
@Column(length = 2048)
|
||||
@DefaultValue("'http://localhost:4200/sso/notification'")
|
||||
public String notification;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Expiration time ")
|
||||
@DefaultValue("666")
|
||||
public Integer ttl;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Right is manage with Karso")
|
||||
@DefaultValue("0")
|
||||
public Boolean manageRight;
|
||||
|
||||
public Application() {}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Application{" + "id=" + this.id + ", description='" + this.description + '\'' + ", redirect='"
|
||||
+ this.redirect + '\'' + ", redirectDev='" + this.redirectDev + '\'' + ", notification='"
|
||||
+ this.notification + '\'' + ", ttl='" + this.ttl + '\'' + '}';
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ApplicationSmall {
|
||||
public Long id;
|
||||
public String name;
|
||||
public String description;
|
||||
public String redirect;
|
||||
|
||||
public ApplicationSmall() {}
|
||||
|
||||
public ApplicationSmall(final Long id, final String name, final String description, final String redirect) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.redirect = redirect;
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.GenericToken;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Table(name = "applicationToken")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ApplicationToken extends GenericToken {
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.checker.CheckJPA;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ChangePassword {
|
||||
@NotNull
|
||||
@Size(min = 2, max = 2)
|
||||
@Pattern(regexp = "^v1$")
|
||||
public String method;
|
||||
@NotNull
|
||||
@Size(min = 3, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9\\-_ \\.@]+$")
|
||||
public String login;
|
||||
@NotNull
|
||||
@Size(min = 20, max = 64)
|
||||
@Pattern(regexp = "^\\d{4}\\-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})+.*$")
|
||||
public String time;
|
||||
@NotNull
|
||||
@Size(min = 128, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
|
||||
public String password;
|
||||
@NotNull
|
||||
@Size(min = 128, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
|
||||
public String newPassword;
|
||||
|
||||
public static class ChangePasswordChecker extends CheckJPA<ChangePassword> {
|
||||
public ChangePasswordChecker() {
|
||||
super(ChangePassword.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ClientToken {
|
||||
@Column(length = 1024)
|
||||
public String url;
|
||||
@Column(length = 0)
|
||||
public String jwt;
|
||||
|
||||
public ClientToken() {
|
||||
|
||||
}
|
||||
|
||||
public ClientToken(final String url, final String jwt) {
|
||||
this.url = url;
|
||||
this.jwt = jwt;
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class CreateTokenRequest {
|
||||
public CreateTokenRequest() {}
|
||||
|
||||
public CreateTokenRequest(final String name, final Integer validity) {
|
||||
this.name = name;
|
||||
this.validity = validity;
|
||||
}
|
||||
|
||||
public String name;
|
||||
public Integer validity;
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import org.kar.archidata.checker.CheckJPA;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class DataGetToken {
|
||||
@NotNull
|
||||
@Size(min = 3, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9\\-_ \\.@]+$")
|
||||
public String login;
|
||||
@NotNull
|
||||
@Size(min = 2, max = 2)
|
||||
@Pattern(regexp = "^v1$")
|
||||
public String method;
|
||||
@NotNull
|
||||
@Size(min = 20, max = 64)
|
||||
@Pattern(regexp = "^\\d{4}\\-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})+.*$")
|
||||
public String time;
|
||||
@NotNull
|
||||
@Size(min = 128, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
|
||||
public String password;
|
||||
|
||||
public static class DataGetTokenChecker extends CheckJPA<DataGetToken> {
|
||||
public DataGetTokenChecker() {
|
||||
super(DataGetToken.class);
|
||||
}
|
||||
}
|
||||
|
||||
public DataGetToken(final String login, final String password, final String time, final String method) {
|
||||
this.method = method;
|
||||
this.login = login;
|
||||
this.time = time;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public DataGetToken() {
|
||||
|
||||
}
|
||||
|
||||
public static String sha512(final String passwordToHash) { //, String salt){
|
||||
String generatedPassword = null;
|
||||
try {
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
//md.update(salt.getBytes(StandardCharsets.UTF_8));
|
||||
final byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final byte element : bytes) {
|
||||
sb.append(Integer.toString((element & 0xff) + 0x100, 16).substring(1));
|
||||
}
|
||||
generatedPassword = sb.toString();
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return generatedPassword;
|
||||
}
|
||||
|
||||
public static DataGetToken generate(final String login, final String password) {
|
||||
return generate(login, password, ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
|
||||
}
|
||||
|
||||
public static DataGetToken generate(final String login, final String password, final String time) {
|
||||
return generate(login, password, time, "v1");
|
||||
}
|
||||
|
||||
public static DataGetToken generate(
|
||||
final String login,
|
||||
final String password,
|
||||
final String time,
|
||||
final String method) {
|
||||
return generateSha(login, sha512(password), time, method);
|
||||
}
|
||||
|
||||
public static DataGetToken generateSha(
|
||||
final String login,
|
||||
final String password,
|
||||
final String time,
|
||||
final String method) {
|
||||
return new DataGetToken(login, sha512("login='" + login + "';pass='" + password + "';date='" + time + "'"),
|
||||
time, method);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class DataGetTokenApplication {
|
||||
public String application;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.annotation.DataJson;
|
||||
import org.kar.archidata.filter.PartRight;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Table(name = "right")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Right extends GenericDataSoftDelete {
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "application-ID that have the reference of the right")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Application.class)
|
||||
public Long applicationId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "user-ID ")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserAuth.class)
|
||||
public Long userId;
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "rightDescription-ID of the right description")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = RightDescription.class)
|
||||
public Long rightDescriptionId;
|
||||
@Column(length = 1024, nullable = false)
|
||||
@Schema(description = "Value of the right")
|
||||
@DataJson
|
||||
public PartRight value;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Table(name = "rightDescription")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class RightDescription extends GenericDataSoftDelete {
|
||||
@Column(nullable = false)
|
||||
@Schema(description = "Application id that have the reference of the right")
|
||||
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Application.class)
|
||||
public Long applicationId;
|
||||
@Column(length = 64, nullable = false)
|
||||
@Schema(description = "Key of the property")
|
||||
public String key;
|
||||
@Column(length = 1024, nullable = false)
|
||||
@Schema(description = "Title of the right")
|
||||
public String title;
|
||||
@Column(length = 1024, nullable = false)
|
||||
@Schema(description = "Description of the right")
|
||||
public String description;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.GenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
|
||||
enum PropertyType {
|
||||
STRING, NUMBER, BOOLEAN,
|
||||
}
|
||||
|
||||
@Table(name = "settings")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Settings extends GenericDataSoftDelete {
|
||||
@Column(length = 512, nullable = false)
|
||||
public String key;
|
||||
@Schema(description = "Right for the specific element(ADMIN [rw] USER [rw] other [rw])")
|
||||
@Column(length = 6, nullable = false)
|
||||
@DefaultValue("\"rw----\"")
|
||||
public String right;
|
||||
@Schema(description = "Type Of the data")
|
||||
@Column(length = 10, nullable = false)
|
||||
public String type;
|
||||
@Schema(description = "Value of the configuration")
|
||||
@Column(nullable = false)
|
||||
public String value;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Settings [key=" + this.key + ", value=" + this.value + ", id=" + this.id + ", deleted=" + this.deleted
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.checker.CheckJPA;
|
||||
import org.kar.archidata.model.User;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
|
||||
@Table(name = "user")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserAuth extends User {
|
||||
@Column(length = 128, nullable = false)
|
||||
@Size(min = 128, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
|
||||
@Nullable
|
||||
public String password;
|
||||
/*
|
||||
@Column(length = 128)
|
||||
public String passwordChange; //!< When change a password, the new password is set in temporary area and wait the email validation
|
||||
@Column(length = 128)
|
||||
public String passwordValidation; //!< UniqueId to validate the new password
|
||||
*/
|
||||
@Column(length = 512, nullable = false)
|
||||
@Size(min = 5, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9\\-\\._]+@[a-zA-Z0-9\\-_]+\\.[a-zA-Z0-9]+$")
|
||||
public String email;
|
||||
public Timestamp emailValidate; // time of validation
|
||||
@Column(length = 512)
|
||||
@Size(min = 5, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9\\-\\._]+@[a-zA-Z0-9\\-_]+\\.[a-zA-Z0-9]+$")
|
||||
public String newEmail;
|
||||
@DefaultValue("'0'")
|
||||
@Column(nullable = false)
|
||||
public Boolean avatar = false;
|
||||
@Schema(description = "List of accessible application (if not set the application is not available)")
|
||||
@ManyToMany(targetEntity = Application.class)
|
||||
public List<Long> applications = null;
|
||||
|
||||
public static class UserAuthChecker extends CheckJPA<UserAuth> {
|
||||
public UserAuthChecker() {
|
||||
super(UserAuth.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.User;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
|
||||
@Table(name = "user")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserAuthGet extends User {
|
||||
@Column(length = 512, nullable = false)
|
||||
public String email;
|
||||
@DefaultValue("'0'")
|
||||
@Column(nullable = false)
|
||||
public Boolean avatar = false;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
import org.kar.archidata.checker.CheckJPA;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserCreate {
|
||||
@NotNull
|
||||
@Size(min = 3, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9\\-_ \\.@]+$")
|
||||
public String login;
|
||||
@NotNull
|
||||
@Size(min = 5, max = 128)
|
||||
@Email()
|
||||
public String email;
|
||||
@NotNull
|
||||
@Size(min = 128, max = 128)
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
|
||||
public String password;
|
||||
|
||||
public static class UserCreateChecker extends CheckJPA<UserCreate> {
|
||||
public UserCreateChecker() {
|
||||
super(UserCreate.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package org.kar.karso.model;
|
||||
|
||||
/*
|
||||
|
||||
CREATE TABLE `application` (
|
||||
`id` bigint NOT NULL COMMENT 'Unique ID of the application' AUTO_INCREMENT PRIMARY KEY,
|
||||
`description` text COMMENT 'description of the application',
|
||||
`token` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'Token (can be not unique)'
|
||||
) AUTO_INCREMENT=10;
|
||||
|
||||
*/
|
||||
|
||||
import org.kar.archidata.annotation.DataIfNotExists;
|
||||
import org.kar.archidata.model.OIDGenericDataSoftDelete;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
// TODO: remove this, it must be generated instead of manually create ///
|
||||
@Table(name = "user_link_application")
|
||||
@DataIfNotExists
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UserLinkApplication extends OIDGenericDataSoftDelete {
|
||||
@Column(name = "object1id")
|
||||
public Long userId;
|
||||
@Column(name = "object2id")
|
||||
public Long applicationId;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.kar.karso.old;
|
||||
|
||||
public class Group {
|
||||
// Unique ID of the group
|
||||
public long id;
|
||||
// Unique ID of the parent group
|
||||
public long parentGroupId = -1;
|
||||
// Name of the group (Must be unique)
|
||||
public String groupName;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.kar.karso.old;
|
||||
|
||||
public class Package {
|
||||
// Unique ID of the package/module
|
||||
public long id;
|
||||
// name of the package
|
||||
public String name;
|
||||
// version of the package
|
||||
public String version;
|
||||
// current coverage of the package
|
||||
public double coverage;
|
||||
// have module deployed
|
||||
public long refBinary;
|
||||
// have test deployed
|
||||
public long refTest;
|
||||
// have source deployed
|
||||
public long refSource;
|
||||
// have java-doc deployed
|
||||
public long refJavaDoc;
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.kar.karso.util;
|
||||
|
||||
public class ConfigVariable {
|
||||
public static String BASE_NAME = "ORG_KARAUTH_";
|
||||
public static String frontFolder = System.getenv(BASE_NAME + "FRONT_FOLDER");
|
||||
public static String expirationTime = System.getenv(BASE_NAME + "AUTH_EXPIRATION_TIME");
|
||||
public static String uuid_for_key_generation = System.getenv(BASE_NAME + "UUID_KEY_ROOT");
|
||||
public static String edge = System.getenv(BASE_NAME + "EDGE");
|
||||
|
||||
public static String getFrontFolder() {
|
||||
if (frontFolder == null) {
|
||||
return "/application/front";
|
||||
}
|
||||
return frontFolder;
|
||||
}
|
||||
|
||||
public static String getUUIDKeyRoot() {
|
||||
return uuid_for_key_generation;
|
||||
}
|
||||
|
||||
public static int getAuthExpirationTime() {
|
||||
String out = expirationTime;
|
||||
if (out == null) {
|
||||
// default expiration is 33 days for the master Oauth token
|
||||
return 60 * 24 * 33;
|
||||
}
|
||||
return Integer.valueOf(out);
|
||||
}
|
||||
|
||||
public static Boolean getEdge() {
|
||||
return Boolean.valueOf(edge);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package org.kar.karso.util;
|
||||
|
||||
public class Transform {
|
||||
|
||||
public static Object convertToType(String type, String value) {
|
||||
if ("BOOLEAN".equals(type)) {
|
||||
return Boolean.valueOf(value);
|
||||
} else if ("STRING".equals(type)) {
|
||||
return value;
|
||||
} else if ("LONG".equals(type)) {
|
||||
return Long.valueOf(value);
|
||||
} else if ("NUMBER".equals(type)) {
|
||||
return Double.valueOf(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String convertToStringCheck(String type, Object value) {
|
||||
if ("BOOLEAN".equals(type)) {
|
||||
if (value instanceof Boolean tmp) {
|
||||
return String.valueOf(tmp);
|
||||
}
|
||||
} else if ("STRING".equals(type)) {
|
||||
if (value instanceof String tmp) {
|
||||
return tmp;
|
||||
}
|
||||
} else if ("LONG".equals(type)) {
|
||||
if (value instanceof Long tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Integer tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Short tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Float tmp) {
|
||||
return String.valueOf(Math.round(tmp));
|
||||
} else if (value instanceof Double tmp) {
|
||||
return String.valueOf(Math.round(tmp));
|
||||
}
|
||||
} else if ("NUMBER".equals(type)) {
|
||||
if (value instanceof Long tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Integer tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Short tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Float tmp) {
|
||||
return String.valueOf(tmp);
|
||||
} else if (value instanceof Double tmp) {
|
||||
return String.valueOf(tmp);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package test.kar.karso;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.dataAccess.DBAccess;
|
||||
import org.kar.archidata.db.DbConfig;
|
||||
import org.kar.archidata.db.DbIoFactory;
|
||||
import org.kar.archidata.exception.DataAccessException;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.karso.api.RightResource;
|
||||
import org.kar.karso.model.Application;
|
||||
import org.kar.karso.model.Right;
|
||||
import org.kar.karso.model.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.InternalServerErrorException;
|
||||
|
||||
public class ConfigureDb {
|
||||
final static private Logger LOGGER = LoggerFactory.getLogger(ConfigureDb.class);
|
||||
final static private String modeTestForced = null;// "MONGO";
|
||||
public static DBAccess da = null;
|
||||
|
||||
public static void configure() throws IOException, InternalServerErrorException, DataAccessException {
|
||||
String modeTest = System.getenv("TEST_E2E_MODE");
|
||||
if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) {
|
||||
modeTest = "SQLITE-MEMORY";
|
||||
} else if ("true".equalsIgnoreCase(modeTest)) {
|
||||
modeTest = "MY-SQL";
|
||||
}
|
||||
// override the local test:
|
||||
if (modeTestForced != null) {
|
||||
modeTest = modeTestForced;
|
||||
}
|
||||
// for local test:
|
||||
ConfigBaseVariable.apiAdress = "http://127.0.0.1:12342/test/api/";
|
||||
// Enable the test mode permit to access to the test token (never use it in production).
|
||||
ConfigBaseVariable.testMode = "true";
|
||||
final List<Class<?>> listObject = List.of( //
|
||||
Application.class, //
|
||||
RightResource.class, //
|
||||
Right.class, //
|
||||
Settings.class //
|
||||
);
|
||||
if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) {
|
||||
ConfigBaseVariable.dbType = "sqlite";
|
||||
ConfigBaseVariable.bdDatabase = null;
|
||||
ConfigBaseVariable.dbHost = "memory";
|
||||
// for test we need to connect all time the DB
|
||||
ConfigBaseVariable.dbKeepConnected = "true";
|
||||
} else if ("SQLITE".equalsIgnoreCase(modeTest)) {
|
||||
ConfigBaseVariable.dbType = "sqlite";
|
||||
ConfigBaseVariable.bdDatabase = null;
|
||||
ConfigBaseVariable.dbKeepConnected = "true";
|
||||
} else if ("MY-SQL".equalsIgnoreCase(modeTest)) {
|
||||
ConfigBaseVariable.dbType = "mysql";
|
||||
ConfigBaseVariable.bdDatabase = "test_karso_db";
|
||||
ConfigBaseVariable.dbPort = "3906";
|
||||
ConfigBaseVariable.dbUser = "root";
|
||||
} else if ("MONGO".equalsIgnoreCase(modeTest)) {
|
||||
ConfigBaseVariable.dbType = "mongo";
|
||||
ConfigBaseVariable.bdDatabase = "test_karso_db";
|
||||
} else {
|
||||
// User local modification ...
|
||||
ConfigBaseVariable.bdDatabase = "test_karso_db";
|
||||
ConfigBaseVariable.dbPort = "3906";
|
||||
ConfigBaseVariable.dbUser = "root";
|
||||
}
|
||||
removeDB();
|
||||
// Connect the dataBase...
|
||||
da = DBAccess.createInterface();
|
||||
}
|
||||
|
||||
public static void removeDB() {
|
||||
String modeTest = System.getenv("TEST_E2E_MODE");
|
||||
if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) {
|
||||
modeTest = "SQLITE-MEMORY";
|
||||
} else if ("true".equalsIgnoreCase(modeTest)) {
|
||||
modeTest = "MY-SQL";
|
||||
}
|
||||
// override the local test:
|
||||
if (modeTestForced != null) {
|
||||
modeTest = modeTestForced;
|
||||
}
|
||||
DbConfig config = null;
|
||||
try {
|
||||
config = new DbConfig();
|
||||
} catch (final DataAccessException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Fail to clean the DB");
|
||||
return;
|
||||
}
|
||||
config.setDbName(null);
|
||||
LOGGER.info("Remove the DB and create a new one '{}'", config.getDbName());
|
||||
try (final DBAccess daRoot = DBAccess.createInterface(config)) {
|
||||
if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) {
|
||||
// nothing to do ...
|
||||
} else if ("SQLITE".equalsIgnoreCase(modeTest)) {
|
||||
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
|
||||
} else if ("MY-SQL".equalsIgnoreCase(modeTest)) {
|
||||
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
|
||||
} else if ("MONGO".equalsIgnoreCase(modeTest)) {
|
||||
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
|
||||
}
|
||||
daRoot.createDB(ConfigBaseVariable.bdDatabase);
|
||||
} catch (final InternalServerErrorException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Fail to clean the DB");
|
||||
return;
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Fail to clean the DB");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() throws IOException {
|
||||
LOGGER.info("Remove the test db");
|
||||
removeDB();
|
||||
// The connection is by default open ==> close it at the end of test:
|
||||
da.close();
|
||||
DbIoFactory.closeAllForceMode();
|
||||
ConfigBaseVariable.clearAllValue();
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package test.kar.karso;
|
||||
|
||||
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
|
||||
import org.junit.jupiter.api.extension.ExecutionCondition;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
|
||||
|
||||
class StepwiseExtension implements ExecutionCondition, TestExecutionExceptionHandler {
|
||||
@Override
|
||||
public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext extensionContext) {
|
||||
final ExtensionContext.Namespace namespace = namespaceFor(extensionContext);
|
||||
final ExtensionContext.Store store = storeFor(extensionContext, namespace);
|
||||
final String value = store.get(StepwiseExtension.class, String.class);
|
||||
return value == null ? ConditionEvaluationResult.enabled("No test failures in stepwise tests")
|
||||
: ConditionEvaluationResult
|
||||
.disabled(String.format("Stepwise test disabled due to previous failure in '%s'", value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTestExecutionException(final ExtensionContext extensionContext, final Throwable throwable)
|
||||
throws Throwable {
|
||||
final ExtensionContext.Namespace namespace = namespaceFor(extensionContext);
|
||||
final ExtensionContext.Store store = storeFor(extensionContext, namespace);
|
||||
store.put(StepwiseExtension.class, extensionContext.getDisplayName());
|
||||
throw throwable;
|
||||
}
|
||||
|
||||
private ExtensionContext.Namespace namespaceFor(final ExtensionContext extensionContext) {
|
||||
return ExtensionContext.Namespace.create(StepwiseExtension.class, extensionContext.getParent());
|
||||
}
|
||||
|
||||
private ExtensionContext.Store storeFor(
|
||||
final ExtensionContext extensionContext,
|
||||
final ExtensionContext.Namespace namespace) {
|
||||
return extensionContext.getParent().get().getStore(namespace);
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package test.kar.karso;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
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.filter.PartRight;
|
||||
import org.kar.archidata.filter.RightSafeCaster;
|
||||
import org.kar.archidata.model.GetToken;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.JWTWrapper;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
import org.kar.karso.model.DataGetToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
|
||||
@ExtendWith(StepwiseExtension.class)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class TestBase {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(TestBase.class);
|
||||
|
||||
static WebLauncherTest webInterface = null;
|
||||
static RESTApi api = null;
|
||||
|
||||
public void login(final String login, final String password) {
|
||||
try {
|
||||
final GetToken token = api.post(GetToken.class, "users/get_token", DataGetToken.generate(login, password));
|
||||
api.setToken(token.jwt);
|
||||
} catch (final Exception ex) {
|
||||
Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void loginAdmin() {
|
||||
login("karadmin", "adminA@666");
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void configureWebServer() throws Exception {
|
||||
ConfigureDb.configure();
|
||||
LOGGER.info("configure server ...");
|
||||
webInterface = new WebLauncherTest();
|
||||
webInterface.migrateDB();
|
||||
LOGGER.info("Start REST (BEGIN)");
|
||||
webInterface.process();
|
||||
LOGGER.info("Start REST (DONE)");
|
||||
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopWebServer() throws InterruptedException, IOException {
|
||||
LOGGER.info("Kill the web server");
|
||||
webInterface.stop();
|
||||
webInterface = null;
|
||||
ConfigureDb.clear();
|
||||
}
|
||||
|
||||
@Order(3)
|
||||
@Test
|
||||
public void firstUserConnect() throws Exception {
|
||||
final GetToken result = api.post(GetToken.class, "users/get_token",
|
||||
DataGetToken.generate("karadmin", "adminA@666", "2025-15-25T22:32:23.252Z"));
|
||||
final String[] splitted = result.jwt.split("\\.");
|
||||
Assertions.assertEquals(3, splitted.length);
|
||||
final String authorization = result.jwt;
|
||||
LOGGER.debug(" validate token : " + authorization);
|
||||
// Note with local access we get the internal key of the system.
|
||||
final JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null);
|
||||
// check the token is valid !!! (signed and coherent issuer...
|
||||
Assertions.assertNotNull(ret);
|
||||
// check userID
|
||||
final String userUID = ret.getSubject();
|
||||
final long id = Long.parseLong(userUID);
|
||||
Assertions.assertEquals(1, id);
|
||||
final String name = (String) ret.getClaim("login");
|
||||
Assertions.assertEquals("karadmin", name);
|
||||
|
||||
final Object rowRight = ret.getClaim("right");
|
||||
Assertions.assertNotNull(rowRight);
|
||||
final Map<String, Map<String, PartRight>> rights = RightSafeCaster.safeCastAndTransform(ret.getClaim("right"));
|
||||
// Check if the element contain the basic keys:
|
||||
Assertions.assertEquals(rights.size(), 1);
|
||||
Assertions.assertTrue(rights.containsKey("karso"));
|
||||
final Map<String, PartRight> applRight = rights.get("karso");
|
||||
//logger.error("full right: {}", applRight);
|
||||
Assertions.assertEquals(applRight.size(), 2);
|
||||
Assertions.assertTrue(applRight.containsKey("ADMIN"));
|
||||
Assertions.assertEquals(PartRight.READ_WRITE, applRight.get("ADMIN"));
|
||||
Assertions.assertTrue(applRight.containsKey("USER"));
|
||||
Assertions.assertEquals(PartRight.READ_WRITE, applRight.get("USER"));
|
||||
|
||||
//logger.debug("request user: '{}' right: '{}' row='{}'", userUID, applRight, rowRight);
|
||||
|
||||
//Assertions.assertEquals("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9", splitted[0]);
|
||||
//Assertions.assertEquals("eyJzdWIiOiIwIiwiYXBwbGljYXRpb24iOiJrYXJzbyIsImlzcyI6IkthckF1dGgiLCJyaWdodCI6eyJrYXJzbyI6eyJBRE1JTiI6dHJ1ZSwiVVNFUiI6dHJ1ZX19LCJsb2dpbiI6ImthcmFkbWluIiwiZXhwIjoxNjg0MTk5MTkzLCJpYXQiOjE2ODI3NTU0MjV9", splitted[1]);
|
||||
// TODO ... Assertions.assertEquals("????", splitted[2]);
|
||||
}
|
||||
|
||||
@Order(5)
|
||||
@Test
|
||||
public void testMeWithToken() throws Exception {
|
||||
loginAdmin();
|
||||
final String result = api.get(String.class, "users/me");
|
||||
Assertions.assertEquals("{\"id\":1,\"login\":\"karadmin\"}", result);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package test.kar.karso;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.exception.RESTErrorResponseException;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
import org.kar.karso.api.HealthCheck.HealthResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ExtendWith(StepwiseExtension.class)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class TestHealthCheck {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(TestHealthCheck.class);
|
||||
|
||||
static WebLauncherTest webInterface = null;
|
||||
static RESTApi api = null;
|
||||
|
||||
@BeforeAll
|
||||
public static void configureWebServer() throws Exception {
|
||||
ConfigureDb.configure();
|
||||
LOGGER.info("configure server ...");
|
||||
webInterface = new WebLauncherTest();
|
||||
webInterface.migrateDB();
|
||||
LOGGER.info("Start REST (BEGIN)");
|
||||
webInterface.process();
|
||||
LOGGER.info("Start REST (DONE)");
|
||||
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopWebServer() throws InterruptedException, IOException {
|
||||
LOGGER.info("Kill the web server");
|
||||
webInterface.stop();
|
||||
webInterface = null;
|
||||
ConfigureDb.clear();
|
||||
}
|
||||
|
||||
@Order(1)
|
||||
@Test
|
||||
//@RepeatedTest(10)
|
||||
public void checkHealthCheck() throws Exception {
|
||||
final HealthResult result = api.get(HealthResult.class, "health_check");
|
||||
Assertions.assertEquals(result.value(), "alive and kicking");
|
||||
}
|
||||
|
||||
@Order(2)
|
||||
@Test
|
||||
public void checkHealthCheckWrongAPI() throws Exception {
|
||||
Assertions.assertThrows(RESTErrorResponseException.class, () -> api.get(HealthResult.class, "health_checks"));
|
||||
}
|
||||
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
package test.kar.karso;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.kar.archidata.exception.RESTErrorResponseException;
|
||||
import org.kar.archidata.model.GetToken;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
import org.kar.karso.model.DataGetToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class TestUnAuthorizedAPI {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(TestUnAuthorizedAPI.class);
|
||||
|
||||
static WebLauncherTest webInterface = null;
|
||||
static RESTApi api = null;
|
||||
|
||||
public void login(final String login, final String password) {
|
||||
try {
|
||||
final GetToken token = api.post(GetToken.class, "users/get_token", DataGetToken.generate(login, password));
|
||||
api.setToken(token.jwt);
|
||||
} catch (final Exception ex) {
|
||||
Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void loginAdmin() {
|
||||
login("karadmin", "adminA@666");
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void configureWebServer() throws Exception {
|
||||
ConfigureDb.configure();
|
||||
LOGGER.info("configure server ...");
|
||||
webInterface = new WebLauncherTest();
|
||||
webInterface.migrateDB();
|
||||
LOGGER.info("Start REST (BEGIN)");
|
||||
webInterface.process();
|
||||
LOGGER.info("Start REST (DONE)");
|
||||
api = new RESTApi(ConfigBaseVariable.apiAdress);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopWebServer() throws InterruptedException, IOException {
|
||||
LOGGER.info("Kill the web server");
|
||||
webInterface.stop();
|
||||
webInterface = null;
|
||||
ConfigureDb.clear();
|
||||
}
|
||||
|
||||
public void checkFail(final String type, final String urlOffset, final int errorStatus) {
|
||||
checkFail(type, urlOffset, errorStatus, null);
|
||||
}
|
||||
|
||||
public void checkFail(final String type, final String urlOffset, final int errorStatus, final String data) {
|
||||
LOGGER.info("Test API: url={} urlOffset={}", type, urlOffset);
|
||||
try {
|
||||
if ("GET".equals(type)) {
|
||||
api.get(String.class, urlOffset);
|
||||
} else if ("POST".equals(type)) {
|
||||
api.post(String.class, urlOffset, data);
|
||||
} else if ("PATCH".equals(type)) {
|
||||
api.patch(String.class, urlOffset, data);
|
||||
} else if ("DELETE".equals(type)) {
|
||||
api.delete(String.class, urlOffset);
|
||||
}
|
||||
Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'");
|
||||
} catch (final RESTErrorResponseException ex) {
|
||||
if (errorStatus != ex.status) {
|
||||
LOGGER.error("Fail in test with the wrong return errors: {}", ex.toString());
|
||||
}
|
||||
Assertions.assertEquals(errorStatus, ex.status);
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Unexpected throw error: {}", ex);
|
||||
Assertions.fail("Unexpected throws...");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void checkWork(final String type, final String urlOffset) {
|
||||
checkWork(type, urlOffset, null);
|
||||
}
|
||||
|
||||
public void checkWork(final String type, final String urlOffset, final String data) {
|
||||
LOGGER.info("Test API: url={} urlOffset={}", type, urlOffset);
|
||||
try {
|
||||
if ("GET".equals(type)) {
|
||||
api.get(String.class, urlOffset);
|
||||
} else if ("POST".equals(type)) {
|
||||
api.post(String.class, urlOffset, data);
|
||||
} else if ("PATCH".equals(type)) {
|
||||
api.patch(String.class, urlOffset, data);
|
||||
} else if ("DELETE".equals(type)) {
|
||||
api.delete(String.class, urlOffset);
|
||||
}
|
||||
//Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'");
|
||||
} catch (final RESTErrorResponseException ex) {
|
||||
Assertions.fail("Must not fail ... " + ex.toString());
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Unexpected throw error: {}", ex);
|
||||
Assertions.fail("Unexpected throws...");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Order(1)
|
||||
@Test
|
||||
public void checkUnAuthorizedAPI() throws Exception {
|
||||
// /application/
|
||||
checkFail("GET", "application/", 401);
|
||||
checkFail("POST", "application/", 401, "{}");
|
||||
checkFail("PATCH", "application/", 405, "{}"); // does not exist
|
||||
checkFail("DELETE", "application/", 405); // does not exist
|
||||
// /application/{id}
|
||||
checkFail("GET", "application/0", 401);
|
||||
checkFail("PATCH", "application/0", 401, "{}");
|
||||
checkFail("POST", "application/0", 405, "{}");
|
||||
checkFail("DELETE", "application/0", 401);
|
||||
// /application/{id}/*
|
||||
checkFail("GET", "application/0/users", 401);
|
||||
// /application/*
|
||||
checkFail("GET", "application/small", 401);
|
||||
checkFail("GET", "application/get_token", 401);
|
||||
checkFail("GET", "application/return", 401);
|
||||
|
||||
// /application_token/ section:
|
||||
checkFail("GET", "application_token/0", 401);
|
||||
checkFail("DELETE", "application_token/0/5", 401);
|
||||
checkFail("DELETE", "application_token/0/create", 401);
|
||||
|
||||
// /front/*
|
||||
checkFail("GET", "front", 404); // no index in test section
|
||||
// health check
|
||||
checkWork("GET", "health_check");
|
||||
|
||||
// public_key (only application)
|
||||
checkFail("GET", "public_key", 401);
|
||||
checkFail("GET", "public_key/pem", 401);
|
||||
|
||||
// /right
|
||||
checkFail("GET", "right", 401);
|
||||
checkFail("POST", "right", 401, "{}");
|
||||
checkFail("GET", "right/0", 401);
|
||||
checkFail("PATCH", "right/0", 401, "{}");
|
||||
checkFail("DELETE", "right/0", 401);
|
||||
|
||||
// /system_config
|
||||
checkWork("GET", "system_config/is_sign_up_availlable");
|
||||
checkFail("GET", "system_config/key/skjdfhkjsdhfkjsh", 401);
|
||||
checkFail("PATCH", "system_config/key/skjdfhkjsdhfkjsh", 401, "{}");
|
||||
|
||||
// /users
|
||||
checkFail("GET", "users", 401);
|
||||
checkFail("GET", "users/0", 401);
|
||||
checkFail("POST", "users/0/application/0/link", 401, "{}");
|
||||
checkFail("POST", "users/0/set_admin", 401, "{}");
|
||||
checkFail("POST", "users/0/set_blocked", 401, "{}");
|
||||
checkFail("POST", "users", 401, "{}");
|
||||
checkFail("GET", "users/me", 401, "{}");
|
||||
checkFail("POST", "users/password", 401, "{}");
|
||||
checkWork("GET", "users/is_login_exist?login=karadmin");
|
||||
checkWork("GET", "users/is_login_exist?login=jhkjhkjh");
|
||||
checkWork("GET", "users/is_email_exist?email=admin@admin.ZZZ");
|
||||
checkWork("GET", "users/is_email_exist?email=ksjhdkjfhskjdh");
|
||||
// not testable : get_token
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
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.exception.RESTErrorResponseException;
|
||||
import org.kar.archidata.model.GetToken;
|
||||
import org.kar.archidata.tools.ConfigBaseVariable;
|
||||
import org.kar.archidata.tools.RESTApi;
|
||||
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 Exception {
|
||||
ConfigureDb.configure();
|
||||
LOGGER.info("configure server ...");
|
||||
webInterface = new WebLauncherTest();
|
||||
webInterface.migrateDB();
|
||||
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", "adminA@666"));
|
||||
api.setToken(result.jwt);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopWebServer() throws IOException {
|
||||
LOGGER.info("Kill the web server");
|
||||
webInterface.stop();
|
||||
webInterface = null;
|
||||
ConfigureDb.clear();
|
||||
}
|
||||
|
||||
@Order(1)
|
||||
@Test
|
||||
public void getsValue() throws RESTErrorResponseException, 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(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);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
|
||||
package test.kar.karso;
|
||||
|
||||
import org.kar.karso.WebLauncher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class WebLauncherTest extends WebLauncher {
|
||||
final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class);
|
||||
|
||||
public WebLauncherTest() {}
|
||||
}
|
@ -30,63 +30,63 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||
"@chakra-ui/cli": "3.7.0",
|
||||
"@chakra-ui/react": "3.7.0",
|
||||
"@chakra-ui/cli": "3.16.0",
|
||||
"@chakra-ui/react": "3.16.0",
|
||||
"@emotion/react": "11.14.0",
|
||||
"allotment": "1.20.2",
|
||||
"allotment": "1.20.3",
|
||||
"css-mediaquery": "0.1.2",
|
||||
"dayjs": "1.11.13",
|
||||
"history": "5.3.0",
|
||||
"next-themes": "^0.4.4",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-error-boundary": "5.0.0",
|
||||
"react-icons": "5.4.0",
|
||||
"react-router-dom": "7.1.5",
|
||||
"react-select": "5.10.0",
|
||||
"react-icons": "5.5.0",
|
||||
"react-router-dom": "7.5.0",
|
||||
"react-select": "5.10.1",
|
||||
"react-use": "17.6.0",
|
||||
"zod": "3.24.1",
|
||||
"zod": "3.24.2",
|
||||
"zustand": "5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chakra-ui/styled-system": "^2.12.0",
|
||||
"@playwright/test": "1.50.1",
|
||||
"@storybook/addon-actions": "8.5.3",
|
||||
"@storybook/addon-essentials": "8.5.3",
|
||||
"@storybook/addon-links": "8.5.3",
|
||||
"@storybook/addon-mdx-gfm": "8.5.3",
|
||||
"@storybook/react": "8.5.3",
|
||||
"@storybook/react-vite": "8.5.3",
|
||||
"@storybook/theming": "8.5.3",
|
||||
"@playwright/test": "1.51.1",
|
||||
"@storybook/addon-actions": "8.6.12",
|
||||
"@storybook/addon-essentials": "8.6.12",
|
||||
"@storybook/addon-links": "8.6.12",
|
||||
"@storybook/addon-mdx-gfm": "8.6.12",
|
||||
"@storybook/react": "8.6.12",
|
||||
"@storybook/react-vite": "8.6.12",
|
||||
"@storybook/theming": "8.6.12",
|
||||
"@testing-library/jest-dom": "6.6.3",
|
||||
"@testing-library/react": "16.2.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "5.2.2",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/node": "22.13.1",
|
||||
"@types/react": "19.0.8",
|
||||
"@types/react-dom": "19.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.23.0",
|
||||
"@typescript-eslint/parser": "8.23.0",
|
||||
"@types/node": "22.14.1",
|
||||
"@types/react": "19.1.1",
|
||||
"@types/react-dom": "19.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.30.0",
|
||||
"@typescript-eslint/parser": "8.30.0",
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"eslint": "9.20.0",
|
||||
"eslint": "9.24.0",
|
||||
"eslint-plugin-codeceptjs": "1.3.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-react": "7.37.4",
|
||||
"eslint-plugin-react-hooks": "5.1.0",
|
||||
"eslint-plugin-storybook": "0.11.2",
|
||||
"eslint-plugin-react": "7.37.5",
|
||||
"eslint-plugin-react-hooks": "5.2.0",
|
||||
"eslint-plugin-storybook": "0.12.0",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"knip": "5.43.6",
|
||||
"lint-staged": "15.4.3",
|
||||
"npm-check-updates": "^17.1.14",
|
||||
"prettier": "3.4.2",
|
||||
"puppeteer": "24.2.0",
|
||||
"react-is": "19.0.0",
|
||||
"storybook": "8.5.3",
|
||||
"knip": "5.50.3",
|
||||
"lint-staged": "15.5.1",
|
||||
"npm-check-updates": "^17.1.18",
|
||||
"prettier": "3.5.3",
|
||||
"puppeteer": "24.6.1",
|
||||
"react-is": "19.1.0",
|
||||
"storybook": "8.6.12",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.7.3",
|
||||
"vite": "6.1.0",
|
||||
"vitest": "3.0.5"
|
||||
"typescript": "5.8.3",
|
||||
"vite": "6.2.6",
|
||||
"vitest": "3.1.1"
|
||||
}
|
||||
}
|
3151
front/pnpm-lock.yaml
generated
3151
front/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -11,10 +11,11 @@ import {
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
AddUserDataWrite,
|
||||
AddUserData,
|
||||
Application,
|
||||
ApplicationCreate,
|
||||
ApplicationSmall,
|
||||
ApplicationWrite,
|
||||
ApplicationUpdate,
|
||||
ClientToken,
|
||||
Long,
|
||||
RightDescription,
|
||||
@ -37,7 +38,7 @@ export namespace ApplicationResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: AddUserDataWrite,
|
||||
data: AddUserData,
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
@ -55,7 +56,7 @@ export namespace ApplicationResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: ApplicationWrite,
|
||||
data: ApplicationCreate,
|
||||
}): Promise<Application> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -256,12 +257,12 @@ export namespace ApplicationResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: ApplicationWrite,
|
||||
data: ApplicationUpdate,
|
||||
}): Promise<Application> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/application/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
ApplicationToken,
|
||||
CreateTokenRequestWrite,
|
||||
CreateTokenRequest,
|
||||
Integer,
|
||||
Long,
|
||||
ZodApplicationToken,
|
||||
@ -30,7 +30,7 @@ export namespace ApplicationTokenResource {
|
||||
params: {
|
||||
applicationId: Long,
|
||||
},
|
||||
data: CreateTokenRequestWrite,
|
||||
data: CreateTokenRequest,
|
||||
}): Promise<ApplicationToken> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -22,7 +22,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -32,7 +32,9 @@ export namespace DataResource {
|
||||
name: string,
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range?: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -42,7 +44,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
@ -52,7 +54,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -61,7 +63,9 @@ export namespace DataResource {
|
||||
params: {
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -71,7 +75,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
@ -81,7 +85,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
queries,
|
||||
params,
|
||||
data,
|
||||
headers,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
queries: {
|
||||
@ -90,7 +94,9 @@ export namespace DataResource {
|
||||
params: {
|
||||
oid: ObjectId,
|
||||
},
|
||||
data: string,
|
||||
headers?: {
|
||||
Range: string,
|
||||
},
|
||||
}): Promise<object> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -100,7 +106,7 @@ export namespace DataResource {
|
||||
restConfig,
|
||||
params,
|
||||
queries,
|
||||
data,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
/**
|
||||
|
@ -13,7 +13,8 @@ import { z as zod } from "zod"
|
||||
import {
|
||||
Long,
|
||||
Right,
|
||||
RightWrite,
|
||||
RightCreate,
|
||||
RightUpdate,
|
||||
ZodRight,
|
||||
isRight,
|
||||
} from "../model";
|
||||
@ -76,12 +77,12 @@ export namespace RightResource {
|
||||
params: {
|
||||
id: Long,
|
||||
},
|
||||
data: RightWrite,
|
||||
data: RightUpdate,
|
||||
}): Promise<Right> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
endPoint: "/right/{id}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
accept: HTTPMimeType.JSON,
|
||||
},
|
||||
@ -95,7 +96,7 @@ export namespace RightResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: RightWrite,
|
||||
data: RightCreate,
|
||||
}): Promise<Right> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -78,7 +78,7 @@ export namespace SystemConfigResource {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
endPoint: "/system_config/key/{key}",
|
||||
requestType: HTTPRequestModel.PATCH,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
},
|
||||
restConfig,
|
||||
|
@ -11,14 +11,14 @@ import {
|
||||
|
||||
import { z as zod } from "zod"
|
||||
import {
|
||||
ChangePasswordWrite,
|
||||
DataGetTokenWrite,
|
||||
ChangePassword,
|
||||
DataGetToken,
|
||||
GetToken,
|
||||
Long,
|
||||
PartRight,
|
||||
UserAuth,
|
||||
UserAuthGet,
|
||||
UserCreateWrite,
|
||||
UserCreate,
|
||||
UserOut,
|
||||
ZodPartRight,
|
||||
ZodUserAuthGet,
|
||||
@ -35,7 +35,7 @@ export namespace UserResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: ChangePasswordWrite,
|
||||
data: ChangePassword,
|
||||
}): Promise<void> {
|
||||
return RESTRequestVoid({
|
||||
restModel: {
|
||||
@ -52,7 +52,7 @@ export namespace UserResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: UserCreateWrite,
|
||||
data: UserCreate,
|
||||
}): Promise<UserAuthGet> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -137,7 +137,7 @@ export namespace UserResource {
|
||||
data,
|
||||
}: {
|
||||
restConfig: RESTConfig,
|
||||
data: DataGetTokenWrite,
|
||||
data: DataGetToken,
|
||||
}): Promise<GetToken> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
@ -263,7 +263,7 @@ export namespace UserResource {
|
||||
applicationId: Long,
|
||||
userId: Long,
|
||||
},
|
||||
data: {[key: string]: PartRight;},
|
||||
data: {[key: Partial<string>]: PartRight;},
|
||||
}): Promise<PatchApplicationRightTypeReturn> {
|
||||
return RESTRequestJson({
|
||||
restModel: {
|
||||
|
@ -21,19 +21,3 @@ export function isAddUserData(data: any): data is AddUserData {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodAddUserDataWrite = zod.object({
|
||||
userId: ZodLong.nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type AddUserDataWrite = zod.infer<typeof ZodAddUserDataWrite>;
|
||||
|
||||
export function isAddUserDataWrite(data: any): data is AddUserDataWrite {
|
||||
try {
|
||||
ZodAddUserDataWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodAddUserDataWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,22 +24,3 @@ export function isApplicationSmall(data: any): data is ApplicationSmall {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodApplicationSmallWrite = zod.object({
|
||||
id: ZodLong.nullable().optional(),
|
||||
name: zod.string().nullable().optional(),
|
||||
description: zod.string().nullable().optional(),
|
||||
redirect: zod.string().nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type ApplicationSmallWrite = zod.infer<typeof ZodApplicationSmallWrite>;
|
||||
|
||||
export function isApplicationSmallWrite(data: any): data is ApplicationSmallWrite {
|
||||
try {
|
||||
ZodApplicationSmallWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodApplicationSmallWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodGenericToken, ZodGenericTokenWrite } from "./generic-token";
|
||||
import {ZodGenericToken} from "./generic-token";
|
||||
|
||||
export const ZodApplicationToken = ZodGenericToken;
|
||||
|
||||
@ -18,16 +18,3 @@ export function isApplicationToken(data: any): data is ApplicationToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodApplicationTokenWrite = ZodGenericTokenWrite;
|
||||
|
||||
export type ApplicationTokenWrite = zod.infer<typeof ZodApplicationTokenWrite>;
|
||||
|
||||
export function isApplicationTokenWrite(data: any): data is ApplicationTokenWrite {
|
||||
try {
|
||||
ZodApplicationTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodApplicationTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,16 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodInteger} from "./integer";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodApplication = ZodGenericDataSoftDelete.extend({
|
||||
name: zod.string().optional(),
|
||||
description: zod.string().optional(),
|
||||
redirect: zod.string(),
|
||||
redirectDev: zod.string().optional(),
|
||||
notification: zod.string().optional(),
|
||||
name: zod.string().min(1).max(256).optional(),
|
||||
description: zod.string().min(1).max(2048).optional(),
|
||||
redirect: zod.string().min(1).max(2048),
|
||||
redirectDev: zod.string().min(1).max(2048).optional(),
|
||||
notification: zod.string().min(1).max(2048).optional(),
|
||||
/**
|
||||
* Expiration time
|
||||
*/
|
||||
@ -20,6 +21,7 @@ export const ZodApplication = ZodGenericDataSoftDelete.extend({
|
||||
* Right is manage with Karso
|
||||
*/
|
||||
manageRight: zod.boolean(),
|
||||
users: zod.array(ZodLong),
|
||||
|
||||
});
|
||||
|
||||
@ -34,31 +36,61 @@ export function isApplication(data: any): data is Application {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodApplicationWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
name: zod.string().nullable().optional(),
|
||||
description: zod.string().nullable().optional(),
|
||||
redirect: zod.string().optional(),
|
||||
redirectDev: zod.string().nullable().optional(),
|
||||
notification: zod.string().nullable().optional(),
|
||||
export const ZodApplicationUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
name: zod.string().min(1).max(256).nullable().optional(),
|
||||
description: zod.string().min(1).max(2048).nullable().optional(),
|
||||
redirect: zod.string().min(1).max(2048),
|
||||
redirectDev: zod.string().min(1).max(2048).nullable().optional(),
|
||||
notification: zod.string().min(1).max(2048).nullable().optional(),
|
||||
/**
|
||||
* Expiration time
|
||||
*/
|
||||
ttl: ZodInteger.optional(),
|
||||
ttl: ZodInteger,
|
||||
/**
|
||||
* Right is manage with Karso
|
||||
*/
|
||||
manageRight: zod.boolean().optional(),
|
||||
manageRight: zod.boolean(),
|
||||
users: zod.array(ZodLong),
|
||||
|
||||
});
|
||||
|
||||
export type ApplicationWrite = zod.infer<typeof ZodApplicationWrite>;
|
||||
export type ApplicationUpdate = zod.infer<typeof ZodApplicationUpdate>;
|
||||
|
||||
export function isApplicationWrite(data: any): data is ApplicationWrite {
|
||||
export function isApplicationUpdate(data: any): data is ApplicationUpdate {
|
||||
try {
|
||||
ZodApplicationWrite.parse(data);
|
||||
ZodApplicationUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodApplicationWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodApplicationUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodApplicationCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||
name: zod.string().min(1).max(256).nullable().optional(),
|
||||
description: zod.string().min(1).max(2048).nullable().optional(),
|
||||
redirect: zod.string().min(1).max(2048),
|
||||
redirectDev: zod.string().min(1).max(2048).nullable().optional(),
|
||||
notification: zod.string().min(1).max(2048).nullable().optional(),
|
||||
/**
|
||||
* Expiration time
|
||||
*/
|
||||
ttl: ZodInteger,
|
||||
/**
|
||||
* Right is manage with Karso
|
||||
*/
|
||||
manageRight: zod.boolean(),
|
||||
users: zod.array(ZodLong),
|
||||
|
||||
});
|
||||
|
||||
export type ApplicationCreate = zod.infer<typeof ZodApplicationCreate>;
|
||||
|
||||
export function isApplicationCreate(data: any): data is ApplicationCreate {
|
||||
try {
|
||||
ZodApplicationCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodApplicationCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,23 +24,3 @@ export function isChangePassword(data: any): data is ChangePassword {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodChangePasswordWrite = zod.object({
|
||||
method: zod.string().min(2).max(2).optional(),
|
||||
login: zod.string().min(3).max(128).optional(),
|
||||
time: zod.string().min(20).max(64).optional(),
|
||||
password: zod.string().min(128).max(128).optional(),
|
||||
newPassword: zod.string().min(128).max(128).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type ChangePasswordWrite = zod.infer<typeof ZodChangePasswordWrite>;
|
||||
|
||||
export function isChangePasswordWrite(data: any): data is ChangePasswordWrite {
|
||||
try {
|
||||
ZodChangePasswordWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodChangePasswordWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import { z as zod } from "zod";
|
||||
|
||||
|
||||
export const ZodClientToken = zod.object({
|
||||
url: zod.string().optional(),
|
||||
jwt: zod.string().optional(),
|
||||
url: zod.string().max(1024).optional(),
|
||||
jwt: zod.string().max(1024).optional(),
|
||||
|
||||
});
|
||||
|
||||
@ -21,20 +21,3 @@ export function isClientToken(data: any): data is ClientToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodClientTokenWrite = zod.object({
|
||||
url: zod.string().nullable().optional(),
|
||||
jwt: zod.string().nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type ClientTokenWrite = zod.infer<typeof ZodClientTokenWrite>;
|
||||
|
||||
export function isClientTokenWrite(data: any): data is ClientTokenWrite {
|
||||
try {
|
||||
ZodClientTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodClientTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -22,20 +22,3 @@ export function isCreateTokenRequest(data: any): data is CreateTokenRequest {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodCreateTokenRequestWrite = zod.object({
|
||||
name: zod.string().nullable().optional(),
|
||||
validity: ZodInteger.nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type CreateTokenRequestWrite = zod.infer<typeof ZodCreateTokenRequestWrite>;
|
||||
|
||||
export function isCreateTokenRequestWrite(data: any): data is CreateTokenRequestWrite {
|
||||
try {
|
||||
ZodCreateTokenRequestWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodCreateTokenRequestWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -23,22 +23,3 @@ export function isDataGetToken(data: any): data is DataGetToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodDataGetTokenWrite = zod.object({
|
||||
login: zod.string().min(3).max(128).optional(),
|
||||
method: zod.string().min(2).max(2).optional(),
|
||||
time: zod.string().min(20).max(64).optional(),
|
||||
password: zod.string().min(128).max(128).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type DataGetTokenWrite = zod.infer<typeof ZodDataGetTokenWrite>;
|
||||
|
||||
export function isDataGetTokenWrite(data: any): data is DataGetTokenWrite {
|
||||
try {
|
||||
ZodDataGetTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodDataGetTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodGenericData, ZodGenericDataWrite } from "./generic-data";
|
||||
import {ZodGenericData, ZodGenericDataUpdate , ZodGenericDataCreate } from "./generic-data";
|
||||
|
||||
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
|
||||
/**
|
||||
@ -24,16 +24,29 @@ export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelet
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericDataSoftDeleteWrite = ZodGenericDataWrite;
|
||||
export const ZodGenericDataSoftDeleteUpdate = ZodGenericDataUpdate;
|
||||
|
||||
export type GenericDataSoftDeleteWrite = zod.infer<typeof ZodGenericDataSoftDeleteWrite>;
|
||||
export type GenericDataSoftDeleteUpdate = zod.infer<typeof ZodGenericDataSoftDeleteUpdate>;
|
||||
|
||||
export function isGenericDataSoftDeleteWrite(data: any): data is GenericDataSoftDeleteWrite {
|
||||
export function isGenericDataSoftDeleteUpdate(data: any): data is GenericDataSoftDeleteUpdate {
|
||||
try {
|
||||
ZodGenericDataSoftDeleteWrite.parse(data);
|
||||
ZodGenericDataSoftDeleteUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericDataSoftDeleteCreate = ZodGenericDataCreate;
|
||||
|
||||
export type GenericDataSoftDeleteCreate = zod.infer<typeof ZodGenericDataSoftDeleteCreate>;
|
||||
|
||||
export function isGenericDataSoftDeleteCreate(data: any): data is GenericDataSoftDeleteCreate {
|
||||
try {
|
||||
ZodGenericDataSoftDeleteCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
||||
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
|
||||
|
||||
export const ZodGenericData = ZodGenericTiming.extend({
|
||||
/**
|
||||
@ -25,16 +25,29 @@ export function isGenericData(data: any): data is GenericData {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericDataWrite = ZodGenericTimingWrite;
|
||||
export const ZodGenericDataUpdate = ZodGenericTimingUpdate;
|
||||
|
||||
export type GenericDataWrite = zod.infer<typeof ZodGenericDataWrite>;
|
||||
export type GenericDataUpdate = zod.infer<typeof ZodGenericDataUpdate>;
|
||||
|
||||
export function isGenericDataWrite(data: any): data is GenericDataWrite {
|
||||
export function isGenericDataUpdate(data: any): data is GenericDataUpdate {
|
||||
try {
|
||||
ZodGenericDataWrite.parse(data);
|
||||
ZodGenericDataUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodGenericDataUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericDataCreate = ZodGenericTimingCreate;
|
||||
|
||||
export type GenericDataCreate = zod.infer<typeof ZodGenericDataCreate>;
|
||||
|
||||
export function isGenericDataCreate(data: any): data is GenericDataCreate {
|
||||
try {
|
||||
ZodGenericDataCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericDataCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,33 @@ export function isGenericTiming(data: any): data is GenericTiming {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericTimingWrite = zod.object({
|
||||
export const ZodGenericTimingUpdate = zod.object({
|
||||
|
||||
});
|
||||
|
||||
export type GenericTimingWrite = zod.infer<typeof ZodGenericTimingWrite>;
|
||||
export type GenericTimingUpdate = zod.infer<typeof ZodGenericTimingUpdate>;
|
||||
|
||||
export function isGenericTimingWrite(data: any): data is GenericTimingWrite {
|
||||
export function isGenericTimingUpdate(data: any): data is GenericTimingUpdate {
|
||||
try {
|
||||
ZodGenericTimingWrite.parse(data);
|
||||
ZodGenericTimingUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericTimingWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodGenericTimingUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericTimingCreate = zod.object({
|
||||
|
||||
});
|
||||
|
||||
export type GenericTimingCreate = zod.infer<typeof ZodGenericTimingCreate>;
|
||||
|
||||
export function isGenericTimingCreate(data: any): data is GenericTimingCreate {
|
||||
try {
|
||||
ZodGenericTimingCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericTimingCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||
import {ZodTimestamp} from "./timestamp";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodGenericToken = ZodGenericDataSoftDelete.extend({
|
||||
parentId: ZodLong,
|
||||
@ -26,22 +26,3 @@ export function isGenericToken(data: any): data is GenericToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGenericTokenWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
parentId: ZodLong.optional(),
|
||||
name: zod.string().optional(),
|
||||
endValidityTime: ZodTimestamp.optional(),
|
||||
token: zod.string().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type GenericTokenWrite = zod.infer<typeof ZodGenericTokenWrite>;
|
||||
|
||||
export function isGenericTokenWrite(data: any): data is GenericTokenWrite {
|
||||
try {
|
||||
ZodGenericTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGenericTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,19 +20,3 @@ export function isGetSignUpAvailable(data: any): data is GetSignUpAvailable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGetSignUpAvailableWrite = zod.object({
|
||||
signup: zod.boolean(),
|
||||
|
||||
});
|
||||
|
||||
export type GetSignUpAvailableWrite = zod.infer<typeof ZodGetSignUpAvailableWrite>;
|
||||
|
||||
export function isGetSignUpAvailableWrite(data: any): data is GetSignUpAvailableWrite {
|
||||
try {
|
||||
ZodGetSignUpAvailableWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetSignUpAvailableWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,19 +20,3 @@ export function isGetToken(data: any): data is GetToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodGetTokenWrite = zod.object({
|
||||
jwt: zod.string().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type GetTokenWrite = zod.infer<typeof ZodGetTokenWrite>;
|
||||
|
||||
export function isGetTokenWrite(data: any): data is GetTokenWrite {
|
||||
try {
|
||||
ZodGetTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodGetTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ export * from "./object-id"
|
||||
export * from "./part-right"
|
||||
export * from "./public-key"
|
||||
export * from "./rest-error-response"
|
||||
export * from "./rest-input-error"
|
||||
export * from "./right"
|
||||
export * from "./right-description"
|
||||
export * from "./timestamp"
|
||||
|
@ -21,20 +21,3 @@ export function isJwtHeader(data: any): data is JwtHeader {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodJwtHeaderWrite = zod.object({
|
||||
typ: zod.string().max(128).optional(),
|
||||
alg: zod.string().max(128).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type JwtHeaderWrite = zod.infer<typeof ZodJwtHeaderWrite>;
|
||||
|
||||
export function isJwtHeaderWrite(data: any): data is JwtHeaderWrite {
|
||||
try {
|
||||
ZodJwtHeaderWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodJwtHeaderWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -27,25 +27,3 @@ export function isJwtPayload(data: any): data is JwtPayload {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodJwtPayloadWrite = zod.object({
|
||||
sub: zod.string().optional(),
|
||||
application: zod.string().optional(),
|
||||
iss: zod.string().optional(),
|
||||
right: zod.record(zod.string(), zod.record(zod.string(), ZodLong)).optional(),
|
||||
login: zod.string().optional(),
|
||||
exp: ZodLong.optional(),
|
||||
iat: ZodLong.optional(),
|
||||
|
||||
});
|
||||
|
||||
export type JwtPayloadWrite = zod.infer<typeof ZodJwtPayloadWrite>;
|
||||
|
||||
export function isJwtPayloadWrite(data: any): data is JwtPayloadWrite {
|
||||
try {
|
||||
ZodJwtPayloadWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodJwtPayloadWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodJwtHeader, ZodJwtHeaderWrite } from "./jwt-header";
|
||||
import {ZodJwtPayload, ZodJwtPayloadWrite } from "./jwt-payload";
|
||||
import {ZodJwtHeader} from "./jwt-header";
|
||||
import {ZodJwtPayload} from "./jwt-payload";
|
||||
|
||||
export const ZodJwtToken = zod.object({
|
||||
header: ZodJwtHeader,
|
||||
@ -24,21 +24,3 @@ export function isJwtToken(data: any): data is JwtToken {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodJwtTokenWrite = zod.object({
|
||||
header: ZodJwtHeader.optional(),
|
||||
payload: ZodJwtPayload.optional(),
|
||||
signature: zod.string().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type JwtTokenWrite = zod.infer<typeof ZodJwtTokenWrite>;
|
||||
|
||||
export function isJwtTokenWrite(data: any): data is JwtTokenWrite {
|
||||
try {
|
||||
ZodJwtTokenWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodJwtTokenWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,19 +20,3 @@ export function isPublicKey(data: any): data is PublicKey {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodPublicKeyWrite = zod.object({
|
||||
key: zod.string().nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type PublicKeyWrite = zod.infer<typeof ZodPublicKeyWrite>;
|
||||
|
||||
export function isPublicKeyWrite(data: any): data is PublicKeyWrite {
|
||||
try {
|
||||
ZodPublicKeyWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodPublicKeyWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodRestInputError} from "./rest-input-error";
|
||||
import {ZodObjectId} from "./object-id";
|
||||
import {ZodInteger} from "./integer";
|
||||
|
||||
@ -13,6 +14,7 @@ export const ZodRestErrorResponse = zod.object({
|
||||
time: zod.string(),
|
||||
status: ZodInteger,
|
||||
statusMessage: zod.string(),
|
||||
inputError: zod.array(ZodRestInputError).optional(),
|
||||
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodRightDescription = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
@ -14,15 +14,15 @@ export const ZodRightDescription = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Key of the property
|
||||
*/
|
||||
key: zod.string(),
|
||||
key: zod.string().min(1).max(64),
|
||||
/**
|
||||
* Title of the right
|
||||
*/
|
||||
title: zod.string(),
|
||||
title: zod.string().min(1).max(1024),
|
||||
/**
|
||||
* Description of the right
|
||||
*/
|
||||
description: zod.string(),
|
||||
description: zod.string().max(1024),
|
||||
|
||||
});
|
||||
|
||||
@ -37,34 +37,3 @@ export function isRightDescription(data: any): data is RightDescription {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodRightDescriptionWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
/**
|
||||
* Application id that have the reference of the right
|
||||
*/
|
||||
applicationId: ZodLong.optional(),
|
||||
/**
|
||||
* Key of the property
|
||||
*/
|
||||
key: zod.string().optional(),
|
||||
/**
|
||||
* Title of the right
|
||||
*/
|
||||
title: zod.string().optional(),
|
||||
/**
|
||||
* Description of the right
|
||||
*/
|
||||
description: zod.string().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type RightDescriptionWrite = zod.infer<typeof ZodRightDescriptionWrite>;
|
||||
|
||||
export function isRightDescriptionWrite(data: any): data is RightDescriptionWrite {
|
||||
try {
|
||||
ZodRightDescriptionWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodRightDescriptionWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||
import {ZodPartRight} from "./part-right";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodRight = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
@ -23,7 +23,7 @@ export const ZodRight = ZodGenericDataSoftDelete.extend({
|
||||
/**
|
||||
* Value of the right
|
||||
*/
|
||||
value: ZodPartRight,
|
||||
value: ZodPartRight.optional(),
|
||||
|
||||
});
|
||||
|
||||
@ -38,34 +38,65 @@ export function isRight(data: any): data is Right {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodRightWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
export const ZodRightUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
/**
|
||||
* application-ID that have the reference of the right
|
||||
*/
|
||||
applicationId: ZodLong.optional(),
|
||||
applicationId: ZodLong,
|
||||
/**
|
||||
* user-ID
|
||||
*/
|
||||
userId: ZodLong.optional(),
|
||||
userId: ZodLong,
|
||||
/**
|
||||
* rightDescription-ID of the right description
|
||||
*/
|
||||
rightDescriptionId: ZodLong.optional(),
|
||||
rightDescriptionId: ZodLong,
|
||||
/**
|
||||
* Value of the right
|
||||
*/
|
||||
value: ZodPartRight.optional(),
|
||||
value: ZodPartRight.nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type RightWrite = zod.infer<typeof ZodRightWrite>;
|
||||
export type RightUpdate = zod.infer<typeof ZodRightUpdate>;
|
||||
|
||||
export function isRightWrite(data: any): data is RightWrite {
|
||||
export function isRightUpdate(data: any): data is RightUpdate {
|
||||
try {
|
||||
ZodRightWrite.parse(data);
|
||||
ZodRightUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodRightWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodRightUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodRightCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||
/**
|
||||
* application-ID that have the reference of the right
|
||||
*/
|
||||
applicationId: ZodLong,
|
||||
/**
|
||||
* user-ID
|
||||
*/
|
||||
userId: ZodLong,
|
||||
/**
|
||||
* rightDescription-ID of the right description
|
||||
*/
|
||||
rightDescriptionId: ZodLong,
|
||||
/**
|
||||
* Value of the right
|
||||
*/
|
||||
value: ZodPartRight.nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type RightCreate = zod.infer<typeof ZodRightCreate>;
|
||||
|
||||
export function isRightCreate(data: any): data is RightCreate {
|
||||
try {
|
||||
ZodRightCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodRightCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodUser, ZodUserWrite } from "./user";
|
||||
import {ZodUser, ZodUserUpdate , ZodUserCreate } from "./user";
|
||||
|
||||
export const ZodUserAuthGet = ZodUser.extend({
|
||||
email: zod.string(),
|
||||
email: zod.string().min(1).max(512),
|
||||
avatar: zod.boolean(),
|
||||
|
||||
});
|
||||
@ -22,20 +22,3 @@ export function isUserAuthGet(data: any): data is UserAuthGet {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserAuthGetWrite = ZodUserWrite.extend({
|
||||
email: zod.string().optional(),
|
||||
avatar: zod.boolean().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserAuthGetWrite = zod.infer<typeof ZodUserAuthGetWrite>;
|
||||
|
||||
export function isUserAuthGetWrite(data: any): data is UserAuthGetWrite {
|
||||
try {
|
||||
ZodUserAuthGetWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserAuthGetWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodTimestamp} from "./timestamp";
|
||||
import {ZodLong} from "./long";
|
||||
import {ZodUser, ZodUserWrite } from "./user";
|
||||
import {ZodTimestamp} from "./timestamp";
|
||||
import {ZodUser, ZodUserUpdate , ZodUserCreate } from "./user";
|
||||
|
||||
export const ZodUserAuth = ZodUser.extend({
|
||||
password: zod.string().min(128).max(128).optional(),
|
||||
@ -31,27 +31,3 @@ export function isUserAuth(data: any): data is UserAuth {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserAuthWrite = ZodUserWrite.extend({
|
||||
password: zod.string().min(128).max(128).nullable().optional(),
|
||||
email: zod.string().min(5).max(128).optional(),
|
||||
emailValidate: ZodTimestamp.nullable().optional(),
|
||||
newEmail: zod.string().min(5).max(128).nullable().optional(),
|
||||
avatar: zod.boolean().optional(),
|
||||
/**
|
||||
* List of accessible application (if not set the application is not available)
|
||||
*/
|
||||
applications: zod.array(ZodLong).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserAuthWrite = zod.infer<typeof ZodUserAuthWrite>;
|
||||
|
||||
export function isUserAuthWrite(data: any): data is UserAuthWrite {
|
||||
try {
|
||||
ZodUserAuthWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserAuthWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -22,21 +22,3 @@ export function isUserCreate(data: any): data is UserCreate {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserCreateWrite = zod.object({
|
||||
login: zod.string().min(3).max(128).optional(),
|
||||
email: zod.string().min(5).max(128).optional(),
|
||||
password: zod.string().min(128).max(128).optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserCreateWrite = zod.infer<typeof ZodUserCreateWrite>;
|
||||
|
||||
export function isUserCreateWrite(data: any): data is UserCreateWrite {
|
||||
try {
|
||||
ZodUserCreateWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserCreateWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -22,20 +22,3 @@ export function isUserOut(data: any): data is UserOut {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserOutWrite = zod.object({
|
||||
id: ZodLong,
|
||||
login: zod.string().nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserOutWrite = zod.infer<typeof ZodUserOutWrite>;
|
||||
|
||||
export function isUserOutWrite(data: any): data is UserOutWrite {
|
||||
try {
|
||||
ZodUserOutWrite.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserOutWrite' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
*/
|
||||
import { z as zod } from "zod";
|
||||
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
|
||||
import {ZodTimestamp} from "./timestamp";
|
||||
import {ZodUUID} from "./uuid";
|
||||
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
|
||||
|
||||
export const ZodUser = ZodGenericDataSoftDelete.extend({
|
||||
login: zod.string().min(3).max(128),
|
||||
@ -30,8 +30,8 @@ export function isUser(data: any): data is User {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
login: zod.string().min(3).max(128).optional(),
|
||||
export const ZodUserUpdate = ZodGenericDataSoftDeleteUpdate.extend({
|
||||
login: zod.string().min(3).max(128),
|
||||
lastConnection: ZodTimestamp.nullable().optional(),
|
||||
blocked: zod.boolean().nullable().optional(),
|
||||
blockedReason: zod.string().max(512).nullable().optional(),
|
||||
@ -42,14 +42,37 @@ export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
|
||||
|
||||
});
|
||||
|
||||
export type UserWrite = zod.infer<typeof ZodUserWrite>;
|
||||
export type UserUpdate = zod.infer<typeof ZodUserUpdate>;
|
||||
|
||||
export function isUserWrite(data: any): data is UserWrite {
|
||||
export function isUserUpdate(data: any): data is UserUpdate {
|
||||
try {
|
||||
ZodUserWrite.parse(data);
|
||||
ZodUserUpdate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserWrite' error=${e}`);
|
||||
console.log(`Fail to parse data type='ZodUserUpdate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export const ZodUserCreate = ZodGenericDataSoftDeleteCreate.extend({
|
||||
login: zod.string().min(3).max(128),
|
||||
lastConnection: ZodTimestamp.nullable().optional(),
|
||||
blocked: zod.boolean().nullable().optional(),
|
||||
blockedReason: zod.string().max(512).nullable().optional(),
|
||||
/**
|
||||
* List of Id of the specific covers
|
||||
*/
|
||||
covers: zod.array(ZodUUID).nullable().optional(),
|
||||
|
||||
});
|
||||
|
||||
export type UserCreate = zod.infer<typeof ZodUserCreate>;
|
||||
|
||||
export function isUserCreate(data: any): data is UserCreate {
|
||||
try {
|
||||
ZodUserCreate.parse(data);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
console.log(`Fail to parse data type='ZodUserCreate' error=${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,30 +3,29 @@
|
||||
* @copyright 2024, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2
|
||||
*/
|
||||
|
||||
import { RestErrorResponse, isRestErrorResponse } from "./model";
|
||||
import { RestErrorResponse, isRestErrorResponse } from './model';
|
||||
|
||||
export enum HTTPRequestModel {
|
||||
ARCHIVE = "ARCHIVE",
|
||||
DELETE = "DELETE",
|
||||
HEAD = "HEAD",
|
||||
GET = "GET",
|
||||
OPTION = "OPTION",
|
||||
PATCH = "PATCH",
|
||||
POST = "POST",
|
||||
PUT = "PUT",
|
||||
RESTORE = "RESTORE",
|
||||
ARCHIVE = 'ARCHIVE',
|
||||
DELETE = 'DELETE',
|
||||
HEAD = 'HEAD',
|
||||
GET = 'GET',
|
||||
OPTION = 'OPTION',
|
||||
PATCH = 'PATCH',
|
||||
POST = 'POST',
|
||||
PUT = 'PUT',
|
||||
RESTORE = 'RESTORE',
|
||||
}
|
||||
export enum HTTPMimeType {
|
||||
ALL = "*/*",
|
||||
CSV = "text/csv",
|
||||
IMAGE = "image/*",
|
||||
IMAGE_JPEG = "image/jpeg",
|
||||
IMAGE_PNG = "image/png",
|
||||
JSON = "application/json",
|
||||
MULTIPART = "multipart/form-data",
|
||||
OCTET_STREAM = "application/octet-stream",
|
||||
TEXT_PLAIN = "text/plain",
|
||||
ALL = '*/*',
|
||||
CSV = 'text/csv',
|
||||
IMAGE = 'image/*',
|
||||
IMAGE_JPEG = 'image/jpeg',
|
||||
IMAGE_PNG = 'image/png',
|
||||
JSON = 'application/json',
|
||||
MULTIPART = 'multipart/form-data',
|
||||
OCTET_STREAM = 'application/octet-stream',
|
||||
TEXT_PLAIN = 'text/plain',
|
||||
}
|
||||
|
||||
export interface RESTConfig {
|
||||
@ -54,6 +53,14 @@ export interface ModelResponseHttp {
|
||||
data: any;
|
||||
}
|
||||
|
||||
export type ErrorRestApiCallback = (response: Response) => void;
|
||||
|
||||
let errorApiGlobalCallback: ErrorRestApiCallback | undefined = undefined;
|
||||
|
||||
export const setErrorApiGlobalCallback = (callback: ErrorRestApiCallback) => {
|
||||
errorApiGlobalCallback = callback;
|
||||
};
|
||||
|
||||
function isNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === undefined || data === null;
|
||||
}
|
||||
@ -78,6 +85,7 @@ export interface RESTRequestType {
|
||||
data?: any;
|
||||
params?: object;
|
||||
queries?: object;
|
||||
headers?: any;
|
||||
callbacks?: RESTCallbacks;
|
||||
}
|
||||
|
||||
@ -87,15 +95,15 @@ function replaceAll(input, searchValue, replaceValue) {
|
||||
|
||||
function removeTrailingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "undefined";
|
||||
return 'undefined';
|
||||
}
|
||||
return input.replace(/\/+$/, "");
|
||||
return input.replace(/\/+$/, '');
|
||||
}
|
||||
function removeLeadingSlashes(input: string): string {
|
||||
if (isNullOrUndefined(input)) {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
return input.replace(/^\/+/, "");
|
||||
return input.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
export function RESTUrl({
|
||||
@ -133,9 +141,9 @@ export function RESTUrl({
|
||||
}
|
||||
}
|
||||
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
|
||||
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
|
||||
searchParams.append('Authorization', `Bearer ${restConfig.token}`);
|
||||
}
|
||||
return generateUrl + "?" + searchParams.toString();
|
||||
return generateUrl + '?' + searchParams.toString();
|
||||
}
|
||||
|
||||
export function fetchProgress(
|
||||
@ -159,7 +167,7 @@ export function fetchProgress(
|
||||
return new Promise((resolve, reject) => {
|
||||
// Stream the upload progress
|
||||
if (progressUpload) {
|
||||
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
|
||||
xhr.io?.upload.addEventListener('progress', (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
@ -167,7 +175,7 @@ export function fetchProgress(
|
||||
}
|
||||
// Stream the download progress
|
||||
if (progressDownload) {
|
||||
xhr.io?.addEventListener("progress", (dataEvent) => {
|
||||
xhr.io?.addEventListener('progress', (dataEvent) => {
|
||||
if (dataEvent.lengthComputable) {
|
||||
progressDownload(dataEvent.loaded, dataEvent.total);
|
||||
}
|
||||
@ -187,19 +195,19 @@ export function fetchProgress(
|
||||
};
|
||||
}
|
||||
// Check if we have an internal Fail:
|
||||
xhr.io?.addEventListener("error", () => {
|
||||
xhr.io?.addEventListener('error', () => {
|
||||
xhr.io = undefined;
|
||||
reject(new TypeError("Failed to fetch"));
|
||||
reject(new TypeError('Failed to fetch'));
|
||||
});
|
||||
|
||||
// Capture the end of the stream
|
||||
xhr.io?.addEventListener("loadend", () => {
|
||||
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"));
|
||||
reject(new TypeError('Fetch has been aborted'));
|
||||
return;
|
||||
}
|
||||
// Stream is ended, transform in a generic response:
|
||||
@ -209,17 +217,17 @@ export function fetchProgress(
|
||||
});
|
||||
const headersArray = replaceAll(
|
||||
xhr.io.getAllResponseHeaders().trim(),
|
||||
"\r\n",
|
||||
"\n"
|
||||
).split("\n");
|
||||
'\r\n',
|
||||
'\n'
|
||||
).split('\n');
|
||||
headersArray.forEach(function (header) {
|
||||
const firstColonIndex = header.indexOf(":");
|
||||
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, "");
|
||||
response.headers.set(header, '');
|
||||
}
|
||||
});
|
||||
xhr.io = undefined;
|
||||
@ -241,27 +249,29 @@ export function RESTRequest({
|
||||
data,
|
||||
params,
|
||||
queries,
|
||||
headers = {},
|
||||
callbacks,
|
||||
}: RESTRequestType): Promise<ModelResponseHttp> {
|
||||
// Create the URL PATH:
|
||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||
let headers: any = {};
|
||||
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;
|
||||
headers['Accept'] = restModel.accept;
|
||||
}
|
||||
if (restModel.requestType !== HTTPRequestModel.GET &&
|
||||
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
||||
restModel.requestType !== HTTPRequestModel.RESTORE
|
||||
if (
|
||||
restModel.requestType !== HTTPRequestModel.GET &&
|
||||
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
|
||||
restModel.requestType !== HTTPRequestModel.RESTORE
|
||||
) {
|
||||
// if Get we have not a content type, the body is empty
|
||||
if (restModel.contentType !== HTTPMimeType.MULTIPART &&
|
||||
restModel.contentType !== undefined
|
||||
) {
|
||||
if (
|
||||
restModel.contentType !== HTTPMimeType.MULTIPART &&
|
||||
restModel.contentType !== undefined
|
||||
) {
|
||||
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
|
||||
headers["Content-Type"] = restModel.contentType;
|
||||
headers['Content-Type'] = restModel.contentType;
|
||||
}
|
||||
}
|
||||
let body = data;
|
||||
@ -302,19 +312,27 @@ export function RESTRequest({
|
||||
}
|
||||
action
|
||||
.then((response: Response) => {
|
||||
if (
|
||||
errorApiGlobalCallback &&
|
||||
400 <= response.status &&
|
||||
response.status <= 499
|
||||
) {
|
||||
// Detect an error and trigger the generic error callback:
|
||||
errorApiGlobalCallback(response);
|
||||
}
|
||||
if (response.status >= 200 && response.status <= 299) {
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (
|
||||
!isNullOrUndefined(restModel.accept) &&
|
||||
restModel.accept !== contentType
|
||||
) {
|
||||
reject({
|
||||
name: "Model accept type incompatible",
|
||||
name: 'Model accept type incompatible',
|
||||
time: Date().toString(),
|
||||
status: 901,
|
||||
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
|
||||
statusMessage: "Fetch error",
|
||||
error: "rest-tools.ts Wrong type in the message return type",
|
||||
statusMessage: 'Fetch error',
|
||||
error: 'rest-tools.ts Wrong type in the message return type',
|
||||
} as RestErrorResponse);
|
||||
} else if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
@ -324,12 +342,12 @@ export function RESTRequest({
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
name: 'API serialization error',
|
||||
time: Date().toString(),
|
||||
status: 902,
|
||||
message: `REST parse json fail: ${reason}`,
|
||||
statusMessage: "Fetch parse error",
|
||||
error: "rest-tools.ts Wrong message model to parse",
|
||||
statusMessage: 'Fetch parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
} else {
|
||||
@ -349,22 +367,22 @@ export function RESTRequest({
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
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",
|
||||
statusMessage: 'Fetch parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
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",
|
||||
statusMessage: 'Fetch ERROR parse error',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
}
|
||||
@ -374,22 +392,22 @@ export function RESTRequest({
|
||||
.text()
|
||||
.then((dataError: string) => {
|
||||
reject({
|
||||
name: "API serialization error",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
statusMessage: 'Fetch ERROR TEXT FAIL',
|
||||
error: 'rest-tools.ts Wrong message model to parse',
|
||||
} as RestErrorResponse);
|
||||
});
|
||||
});
|
||||
@ -400,12 +418,12 @@ export function RESTRequest({
|
||||
reject(error);
|
||||
} else {
|
||||
reject({
|
||||
name: "Request fail",
|
||||
name: 'Request fail',
|
||||
time: Date(),
|
||||
status: 999,
|
||||
message: error,
|
||||
statusMessage: "Fetch catch error",
|
||||
error: "rest-tools.ts detect an error in the fetch request",
|
||||
statusMessage: 'Fetch catch error',
|
||||
error: 'rest-tools.ts detect an error in the fetch request',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -426,12 +444,12 @@ export function RESTRequestJson<TYPE>(
|
||||
resolve(value.data);
|
||||
} else {
|
||||
reject({
|
||||
name: "Model check fail",
|
||||
name: 'Model check fail',
|
||||
time: Date().toString(),
|
||||
status: 950,
|
||||
error: "REST Fail to verify the data",
|
||||
statusMessage: "API cast ERROR",
|
||||
message: "api.ts Check type as fail",
|
||||
error: 'REST Fail to verify the data',
|
||||
statusMessage: 'API cast ERROR',
|
||||
message: 'api.ts Check type as fail',
|
||||
} as RestErrorResponse);
|
||||
}
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button, Table, Text } from '@chakra-ui/react';
|
||||
import { z as zod } from 'zod';
|
||||
|
||||
import { UserCreateWrite, ZodUserCreateWrite } from '@/back-api';
|
||||
import { UserCreate, ZodUserCreate } from '@/back-api';
|
||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||
import { ParameterLayout } from '@/components/ParameterLayout';
|
||||
import { TopBar } from '@/components/TopBar/TopBar';
|
||||
@ -99,14 +99,14 @@ const passwordSchema = zod
|
||||
message: 'The password must not contain spaces.',
|
||||
});
|
||||
|
||||
export const ZodUserCreateWithNewPassword = ZodUserCreateWrite.omit({
|
||||
export const ZodUserCreateWithNewPassword = ZodUserCreate.omit({
|
||||
password: true,
|
||||
}).extend({
|
||||
password: passwordSchema,
|
||||
});
|
||||
|
||||
export const CreateUserComponent = () => {
|
||||
const form = useFormidable<UserCreateWrite>({
|
||||
const form = useFormidable<UserCreate>({
|
||||
initialValues: {
|
||||
login: '',
|
||||
email: '',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { UserResource } from '@/back-api';
|
||||
import { toaster, toasterAPIError } from '@/components/ui/toaster';
|
||||
import { toaster } from '@/components/ui/toaster';
|
||||
import { useSessionService } from '@/service/session';
|
||||
//import { useSessionContext } from '@/context/SessionContext';
|
||||
import { getRestConfig } from '@/utils/http';
|
||||
@ -51,6 +51,7 @@ export const useLogin = () => {
|
||||
toaster.create({
|
||||
title: 'Connection fail',
|
||||
description: `Fail to connect with identification: '${login}'`,
|
||||
type: 'error',
|
||||
});
|
||||
setLastError('The connection Fail');
|
||||
setIsConnectionLoading(false);
|
||||
|
@ -1,10 +1,9 @@
|
||||
import {
|
||||
ApplicationToken,
|
||||
ApplicationTokenResource,
|
||||
CreateTokenRequestWrite,
|
||||
CreateTokenRequest,
|
||||
Integer,
|
||||
Long,
|
||||
RestErrorResponse,
|
||||
} from '@/back-api';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { useQuery, useQueryCall, useQueryCallProps } from '@/utils/query';
|
||||
@ -26,14 +25,15 @@ export namespace ApplicationTokenService {
|
||||
|
||||
export const useApplicationTokenCreate = (
|
||||
applicationId: Long,
|
||||
config: {
|
||||
config?: Omit<useQueryCallProps<ApplicationToken, any>, 'queryFunction'>;
|
||||
}
|
||||
config: Omit<
|
||||
useQueryCallProps<ApplicationToken, CreateTokenRequest>,
|
||||
'queryFunction'
|
||||
> = {}
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<
|
||||
ApplicationToken,
|
||||
CreateTokenRequestWrite
|
||||
CreateTokenRequest
|
||||
>({
|
||||
queryFunction: (inputData) => {
|
||||
return ApplicationTokenResource.create({
|
||||
@ -49,7 +49,15 @@ export namespace ApplicationTokenService {
|
||||
|
||||
export const useApplicationTokenRemove = (
|
||||
applicationId: Long,
|
||||
config: { config?: Omit<useQueryCallProps<void, any>, 'queryFunction'> }
|
||||
config: Omit<
|
||||
useQueryCallProps<
|
||||
void,
|
||||
{
|
||||
tokenId: Integer;
|
||||
}
|
||||
>,
|
||||
'queryFunction'
|
||||
> = {}
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<
|
||||
|
@ -56,11 +56,12 @@ export namespace ApplicationService {
|
||||
// });
|
||||
// }
|
||||
|
||||
export const useGetClientToken = ({
|
||||
config,
|
||||
}: {
|
||||
config?: Omit<useQueryCallProps<ClientToken, any>, 'queryFunction'>;
|
||||
}) => {
|
||||
export const useGetClientToken = (
|
||||
config: Omit<
|
||||
useQueryCallProps<ClientToken, { application: string }>,
|
||||
'queryFunction'
|
||||
> = {}
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<
|
||||
ClientToken,
|
||||
|
@ -130,14 +130,14 @@ export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||
};
|
||||
};
|
||||
|
||||
export const useHasRight = (part: RightGroup) => {
|
||||
export const useHasRight = (group: RightGroup) => {
|
||||
const { token, hasReadRight, hasWriteRight } = useSessionService();
|
||||
const isReadable = useMemo(() => {
|
||||
console.log(`get is read for: ${part} ==> ${hasReadRight(part)}`);
|
||||
return hasReadRight(part);
|
||||
}, [token, hasReadRight, part]);
|
||||
console.log(`get is read for: ${group} ==> ${hasReadRight(group)}`);
|
||||
return hasReadRight(group);
|
||||
}, [token, hasReadRight, group]);
|
||||
const isWritable = useMemo(() => {
|
||||
return hasWriteRight(part);
|
||||
}, [token, hasWriteRight, part]);
|
||||
return hasWriteRight(group);
|
||||
}, [token, hasWriteRight, group]);
|
||||
return { isReadable, isWritable };
|
||||
};
|
||||
|
@ -3,12 +3,7 @@
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import {
|
||||
RESTConfig,
|
||||
UserAuthGet,
|
||||
UserCreateWrite,
|
||||
UserResource,
|
||||
} from '@/back-api';
|
||||
import { UserAuthGet, UserCreate, UserResource } from '@/back-api';
|
||||
import { useQuery, useQueryCall, useQueryCallProps } from '@/utils/query';
|
||||
|
||||
import { useSessionService } from './session';
|
||||
@ -35,13 +30,14 @@ export namespace UserService {
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useCreate = ({
|
||||
config,
|
||||
}: {
|
||||
config?: Omit<useQueryCallProps<UserAuthGet, any>, 'queryFunction'>;
|
||||
}) => {
|
||||
export const useCreate = (
|
||||
config: Omit<
|
||||
useQueryCallProps<UserAuthGet, UserCreate>,
|
||||
'queryFunction'
|
||||
> = {}
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQueryCall<UserAuthGet, UserCreateWrite>({
|
||||
return useQueryCall<UserAuthGet, UserCreate>({
|
||||
queryFunction: (data) => {
|
||||
return UserResource.create({
|
||||
restConfig: getRestConfig(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user