[DEV] update with the new back

This commit is contained in:
Edouard DUPIN 2025-01-08 22:47:38 +01:00
parent 24c7f83629
commit cbc0705a79
21 changed files with 592 additions and 355 deletions

View File

@ -11,12 +11,12 @@
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name> <name>edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder</name>
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>
<name>edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder</name> <name>org.eclipse.m2e.core.maven2Builder</name>
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>

View File

@ -20,17 +20,29 @@
<dependency> <dependency>
<groupId>kangaroo-and-rabbit</groupId> <groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.11.0</version> <version>0.20.5-SNAPSHOT</version>
</dependency> </dependency>
<!-- Loopback of logger JDK logging API to SLF4J -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>jul-to-slf4j</artifactId>
<version>2.1.0-alpha1</version> <version>2.0.9</version>
</dependency>
<!-- generic logger of SLF4J to console (in color) -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.12.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId> <artifactId>jackson-datatype-jsr310</artifactId>
<version>2.17.1</version> <version>2.18.0-rc1</version>
</dependency> </dependency>
<!-- <!--
************************************************************ ************************************************************
@ -40,15 +52,25 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>5.11.0-M2</version> <version>5.11.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0-M2</version> <version>5.11.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.24.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<sourceDirectory>src</sourceDirectory> <sourceDirectory>src</sourceDirectory>
@ -166,6 +188,23 @@
<nohelp>true</nohelp> <nohelp>true</nohelp>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>exec-application</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.kar.karso.WebLauncher</mainClass>
</configuration>
</plugin>
<!-- Check the style of the code --> <!-- Check the style of the code -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -207,20 +246,20 @@
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>com.github.spotbugs</groupId>
<artifactId>exec-maven-plugin</artifactId> <artifactId>spotbugs-maven-plugin</artifactId>
<version>3.1.0</version> <version>4.8.5.0</version>
<executions>
<execution>
<id>exec-application</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration> <configuration>
<mainClass>org.kar.karso.WebLauncher</mainClass> <includeFilterFile>spotbugs-security-include.xml</includeFilterFile>
<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile>
<!--<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>1.12.0</version>
</plugin>
</plugins>
-->
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -7,18 +7,18 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.UpdateJwtPublicKey; import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource; import org.kar.archidata.api.DataResource;
import org.kar.archidata.backup.BackupEngine; import org.kar.archidata.backup.BackupEngine;
import org.kar.archidata.backup.BackupEngine.StoreMode; import org.kar.archidata.backup.BackupEngine.StoreMode;
import org.kar.archidata.catcher.GenericCatcher; import org.kar.archidata.catcher.GenericCatcher;
import org.kar.archidata.db.DBConfig; import org.kar.archidata.db.DbConfig;
import org.kar.archidata.filter.CORSFilter; import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter; import org.kar.archidata.filter.OptionFilter;
import org.kar.archidata.migration.MigrationEngine; import org.kar.archidata.migration.MigrationEngine;
import org.kar.archidata.migration.model.Migration; import org.kar.archidata.migration.model.Migration;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.ContextGenericTools;
import org.kar.archidata.tools.JWTWrapper; import org.kar.archidata.tools.JWTWrapper;
import org.kar.karso.api.ApplicationResource; import org.kar.karso.api.ApplicationResource;
import org.kar.karso.api.ApplicationTokenResource; import org.kar.karso.api.ApplicationTokenResource;
@ -47,7 +47,6 @@ import jakarta.ws.rs.core.UriBuilder;
public class WebLauncher { public class WebLauncher {
private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class); private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
public static DBConfig dbConfig;
protected UpdateJwtPublicKey keyUpdater = null; protected UpdateJwtPublicKey keyUpdater = null;
protected HttpServer server = null; protected HttpServer server = null;
protected BackupEngine backupEngine = new BackupEngine("./backup", StoreMode.JSON); protected BackupEngine backupEngine = new BackupEngine("./backup", StoreMode.JSON);
@ -78,7 +77,7 @@ public class WebLauncher {
migrationEngine.add(new Migration20231126()); migrationEngine.add(new Migration20231126());
migrationEngine.add(new Migration20240515()); migrationEngine.add(new Migration20240515());
WebLauncher.LOGGER.info("Migrate the DB [START]"); WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); migrationEngine.migrateWaitAdmin(new DbConfig());
WebLauncher.LOGGER.info("Migrate the DB [STOP]"); WebLauncher.LOGGER.info("Migrate the DB [STOP]");
} }
@ -130,11 +129,13 @@ public class WebLauncher {
rc.register(HealthCheck.class); rc.register(HealthCheck.class);
rc.register(Front.class); rc.register(Front.class);
ContextGenericTools.addJsr310(rc);
// add jackson to be discover when we are ins stand-alone server // add jackson to be discover when we are ins stand-alone server
rc.register(JacksonFeature.class); rc.register(JacksonFeature.class);
// enable this to show low level request // enable this to show low level request
//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); //rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());
LOGGER.info("Start http Server: {}", getBaseURI());
this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
final HttpServer serverLink = this.server; final HttpServer serverLink = this.server;
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

View File

@ -6,10 +6,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryAnd; import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.exception.InputException; import org.kar.archidata.exception.InputException;
import org.kar.archidata.exception.SystemException; import org.kar.archidata.exception.SystemException;
@ -96,7 +97,7 @@ public class ApplicationResource {
LOGGER.debug("getApplications"); LOGGER.debug("getApplications");
// TODO filter with the list of element available in his authorizations ... // TODO filter with the list of element available in his authorizations ...
final List<Application> tmp = DataAccess.gets(Application.class); final List<Application> tmp = DataAccess.gets(Application.class);
if (gc.userByToken.hasRight("ADMIN", true)) { if (sc.isUserInRole("ADMIN")) {
return tmp; return tmp;
} }
final List<Long> regular = getUserListOfApplication(gc.userByToken.id); final List<Long> regular = getUserListOfApplication(gc.userByToken.id);
@ -206,7 +207,9 @@ public class ApplicationResource {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public void addUser(@PathParam("id") final Long applicationId, final AddUserData data) throws Exception { public void addUser(@PathParam("id") final Long applicationId, final AddUserData data) throws Exception {
LOGGER.debug("getApplications"); LOGGER.debug("getApplications");
AddOnManyToMany.addLink(UserAuth.class, data.userId, "application", applicationId); try (DBAccess db = DBAccess.createInterface()) {
AddOnManyToMany.addLink(db, UserAuth.class, data.userId, "application", applicationId);
}
} }
@DELETE @DELETE
@ -215,7 +218,9 @@ public class ApplicationResource {
public void removeUser(@PathParam("id") final Long applicationId, @PathParam("userId") final Long userId) public void removeUser(@PathParam("id") final Long applicationId, @PathParam("userId") final Long userId)
throws Exception { throws Exception {
LOGGER.debug("getApplications"); LOGGER.debug("getApplications");
AddOnManyToMany.removeLink(UserAuth.class, userId, "application", applicationId); try (DBAccess db = DBAccess.createInterface()) {
AddOnManyToMany.removeLink(db, UserAuth.class, userId, "application", applicationId);
}
} }
@GET @GET

View File

@ -63,7 +63,7 @@ public class ApplicationTokenResource {
@Context final SecurityContext sc, @Context final SecurityContext sc,
@PathParam("applicationId") final Long applicationId, @PathParam("applicationId") final Long applicationId,
@PathParam("tokenId") final Integer tokenId) throws Exception { @PathParam("tokenId") final Integer tokenId) throws Exception {
final int nbRemoved = DataAccess.deleteWhere(ApplicationToken.class, final long nbRemoved = DataAccess.deleteWhere(ApplicationToken.class,
new Condition(new QueryAnd(new QueryCondition("parentId", "=", applicationId), new Condition(new QueryAnd(new QueryCondition("parentId", "=", applicationId),
new QueryCondition("id", "=", tokenId)))); new QueryCondition("id", "=", tokenId))));
if (nbRemoved == 0) { if (nbRemoved == 0) {

View File

@ -9,22 +9,32 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; 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.Condition;
import org.kar.archidata.dataAccess.options.ReadAllColumn;
import org.kar.archidata.exception.FailException; import org.kar.archidata.exception.FailException;
import org.kar.archidata.exception.InputException;
import org.kar.archidata.exception.SystemException; import org.kar.archidata.exception.SystemException;
import org.kar.archidata.filter.GenericContext; import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.GetToken; import org.kar.archidata.model.GetToken;
import org.kar.archidata.tools.JWTWrapper; import org.kar.archidata.tools.JWTWrapper;
import org.kar.karso.migration.Initialization; import org.kar.karso.migration.Initialization;
import org.kar.karso.model.Application;
import org.kar.karso.model.ChangePassword; 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;
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;
import org.kar.karso.model.UserAuth.UserAuthChecker;
import org.kar.karso.model.UserAuthGet; import org.kar.karso.model.UserAuthGet;
import org.kar.karso.model.UserCreate; import org.kar.karso.model.UserCreate;
import org.kar.karso.model.UserCreate.UserCreateChecker;
import org.kar.karso.util.ConfigVariable; import org.kar.karso.util.ConfigVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -50,6 +60,11 @@ import jakarta.ws.rs.core.SecurityContext;
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public class UserResource { public class UserResource {
private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); 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) @JsonInclude(JsonInclude.Include.NON_NULL)
public static class UserOut { public static class UserOut {
@ -66,16 +81,25 @@ public class UserResource {
@GET @GET
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public List<UserAuthGet> getUsers() throws Exception { public List<UserAuth> gets() throws Exception {
return DataAccess.gets(UserAuthGet.class); return DataAccess.gets(UserAuth.class);
} }
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed({ "ADMIN", "USER" })
public UserAuthGet getUser(@Context final SecurityContext sc, @PathParam("id") final long userId) throws Exception { public UserAuth get(@Context final SecurityContext sc, @PathParam("id") final long id) throws Exception {
//GenericContext gc = (GenericContext) sc.getUserPrincipal(); if (!sc.isUserInRole("ADMIN")) {
return DataAccess.get(UserAuthGet.class, userId); // in case of user we need to check if it get his own id parameters:
final UserAuth ret = DataAccess.get(UserAuth.class, id, new AccessDeletedItems());
return ret;
}
final UserAuth ret = DataAccess.get(UserAuth.class, id);
if (ret != null) {
return ret;
}
// Find element in deleted
return DataAccess.get(UserAuth.class, id, new AccessDeletedItems(), new ReadAllColumn());
} }
@POST @POST
@ -87,12 +111,14 @@ public class UserResource {
@PathParam("applicationId") final long applicationId, @PathParam("applicationId") final long applicationId,
final boolean data) throws Exception { final boolean data) throws Exception {
LOGGER.debug("Find typeNode"); LOGGER.debug("Find typeNode");
try (DBAccess db = DBAccess.createInterface()) {
if (data) { if (data) {
AddOnManyToMany.addLink(UserAuth.class, userId, "application", applicationId); AddOnManyToMany.addLink(db, UserAuth.class, userId, "application", applicationId);
} else { } else {
AddOnManyToMany.removeLink(UserAuth.class, userId, "application", applicationId); AddOnManyToMany.removeLink(db, UserAuth.class, userId, "application", applicationId);
}
return db.get(UserAuth.class, userId);
} }
return DataAccess.get(UserAuth.class, userId);
} }
@GET @GET
@ -126,13 +152,35 @@ public class UserResource {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public void setAdmin(@Context final SecurityContext sc, @PathParam("id") final long userId, final boolean data) public void setAdmin(@Context final SecurityContext sc, @PathParam("id") final long userId, final boolean data)
throws Exception { throws Exception {
final UserAuth user = new UserAuth(); try (DBAccess da = DBAccess.createInterface()) {
user.admin = data; final Application appKarso = da.get(Application.class,
final int ret = DataAccess.update(user, userId, List.of("admin")); 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 = "true";
da.insert(newRight);
return;
} else if (right.value.equals("true")) {
return;
}
right.value = "true";
final long ret = da.update(right, right.id, List.of("value"));
if (ret == 0) { if (ret == 0) {
throw new FailException(Response.Status.NOT_MODIFIED, "Fail to modify user as an admin."); throw new FailException(Response.Status.NOT_MODIFIED, "Fail to modify user as an admin.");
} }
} }
}
@POST @POST
@Path("{id}/set_blocked") @Path("{id}/set_blocked")
@ -142,7 +190,7 @@ public class UserResource {
throws Exception { throws Exception {
final UserAuth user = new UserAuth(); final UserAuth user = new UserAuth();
user.blocked = data; user.blocked = data;
final int ret = DataAccess.update(user, userId, List.of("blocked")); final long ret = DataAccess.update(user, userId, List.of("blocked"));
if (ret == 0) { if (ret == 0) {
throw new FailException(Response.Status.NOT_MODIFIED, "Fail to block the User."); throw new FailException(Response.Status.NOT_MODIFIED, "Fail to block the User.");
} }
@ -153,47 +201,31 @@ public class UserResource {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public UserAuthGet create(final UserCreate user) throws Exception { public UserAuthGet create(final UserCreate user) throws Exception {
LOGGER.debug("create new User email={} login={}", user.email, user.login); LOGGER.debug("create new User email={} login={}", user.email, user.login);
// verify login or email is correct: try (DBAccess da = DBAccess.createInterface()) {
if (user.login == null || user.login.length() < 6) { CHECKER_CREATE_USER.checkAll(da, "", user, null);
throw new InputException("login", "Authentiocate-method-error (login too small: '" + user.login + "')");
}
// TODO: check login format
if (user.email == null || user.email.length() < 6) {
throw new InputException("email", "Authentiocate-method-error (email too small: '" + user.email + "')");
}
// TODO: check email format
if (user.password == null || user.password.length() != 128) {
throw new InputException("password", "null password, or wrong hash size");
}
// TODO: verify if the data are a hash ...
// Check login does not exist // Check login does not exist
List<UserAuth> out = DataAccess.getsWhere(UserAuth.class, List<UserAuth> out = da.getsWhere(UserAuth.class,
new Condition(new QueryCondition("login", "=", user.login))); new Condition(new QueryCondition("login", "=", user.login)));
if (out.size() >= 1) { if (out.size() >= 1) {
throw new FailException(Response.Status.BAD_REQUEST, "Login already used !!!"); throw new FailException(Response.Status.BAD_REQUEST, "Login already used !!!");
} }
// Check email does not exist // Check email does not exist
out = DataAccess.getsWhere(UserAuth.class, new Condition(new QueryCondition("email", "=", user.email))); out = da.getsWhere(UserAuth.class, new Condition(new QueryCondition("email", "=", user.email)));
if (out.size() >= 1) { if (out.size() >= 1) {
throw new FailException(Response.Status.BAD_REQUEST, "e-mail already used !!!"); throw new FailException(Response.Status.BAD_REQUEST, "e-mail already used !!!");
} }
// Add new user and return formated data. // Add new user and return formated data.
final UserAuth newUser = new UserAuth(); final UserAuth newUser = new UserAuth();
newUser.admin = false;
newUser.removed = false;
newUser.blocked = false; newUser.blocked = false;
newUser.avatar = false; newUser.avatar = false;
newUser.login = user.login; newUser.login = user.login;
newUser.password = user.password; newUser.password = user.password;
newUser.email = user.email; newUser.email = user.email;
newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now()); newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now());
final UserAuth tmp = DataAccess.insert(newUser); final UserAuth tmp = da.insert(newUser);
LOGGER.debug("create new user done with id=={}", tmp.id); LOGGER.debug("create new user done with id=={}", tmp.id);
return DataAccess.get(UserAuthGet.class, tmp.id); return da.get(UserAuthGet.class, tmp.id);
}
} }
@GET @GET
@ -214,21 +246,20 @@ public class UserResource {
LOGGER.debug("ChangePassword()"); LOGGER.debug("ChangePassword()");
final GenericContext gc = (GenericContext) sc.getUserPrincipal(); final GenericContext gc = (GenericContext) sc.getUserPrincipal();
LOGGER.debug("== USER ? {}", gc.userByToken); LOGGER.debug("== USER ? {}", gc.userByToken);
try (DBAccess da = DBAccess.createInterface()) {
if (data == null) { CHECKER_CHANGE_PASSWORD.checkAll(da, "", data, null);
throw new InputException("data", "No data set..."); final UserAuth user = checkAuthUser(data.login, data.time, data.password);
}
if (data.newPassword == null || data.newPassword.length() != 128) {
throw new InputException("newPassword", "null password, or wrong hash size");
}
final UserAuth user = checkAuthUser(data.method, data.login, data.time, data.password);
if (user == null) { if (user == null) {
throw new SystemException("Fail to retrieve the user... (impossible case)"); throw new SystemException("Fail to retrieve the user... (impossible case)");
} }
if (user.id != gc.userByToken.id) {
throw new SystemException("Try to change the password of an other user !!! You are BAD...");
}
// Process the update: // Process the update:
user.password = data.newPassword; user.password = data.newPassword;
DataAccess.update(user, user.id, List.of("password")); DataAccess.update(user, user.id, List.of("password"));
} }
}
@GET @GET
@Path("is_login_exist") @Path("is_login_exist")
@ -251,29 +282,18 @@ public class UserResource {
return out.size() >= 1; return out.size() >= 1;
} }
private UserAuth checkAuthUser(final String method, final String login, final String time, final String password) private UserAuth checkAuthUser(final String login, final String time, final String password) throws Exception {
throws Exception {
// check good version:
if (!"v1".contentEquals(method)) {
throw new InputException("method", "Authentiocate-method-error (wrong version: '" + method + "')");
}
// verify login or email is correct:
if (login.length() < 6) {
throw new InputException("login", "Authentiocate-method-error (email or login too small: '" + login + "')");
}
if (password == null || password.length() != 128) {
throw new InputException("password", "null password, or wrong hash size");
}
// email or login? // email or login?
String query = "login"; String query = "login";
if (login.contains("@")) { if (login.contains("@")) {
query = "email"; query = "email";
} }
final UserAuth user = DataAccess.getWhere(UserAuth.class, new Condition(new QueryCondition(query, "=", login))); final UserAuth user = DataAccess.getWhere(UserAuth.class, new Condition(new QueryCondition(query, "=", login)),
new AccessDeletedItems(), new ReadAllColumn());
if (user == null) { if (user == null) {
throw new FailException(Response.Status.PRECONDITION_FAILED, throw new FailException(Response.Status.PRECONDITION_FAILED,
"FAIL Authentiocate-wrong email/login '" + login + "')"); "FAIL Authenticate-wrong email/login '" + login + "')");
} }
// Check the password: // Check the password:
final String passwordCheck = getSHA512( final String passwordCheck = getSHA512(
@ -281,9 +301,8 @@ public class UserResource {
if (!passwordCheck.contentEquals(password)) { if (!passwordCheck.contentEquals(password)) {
throw new FailException(Response.Status.PRECONDITION_FAILED, "Password error ..."); throw new FailException(Response.Status.PRECONDITION_FAILED, "Password error ...");
} }
LOGGER.debug(" ==> pass nearly all test : admin={} blocked={} removed={}", user.admin, user.blocked, LOGGER.debug(" ==> pass nearly all test: blocked={} deleted={} ", user.blocked, user.deleted);
user.removed); if (user.blocked || (user.deleted != null && user.deleted == true)) {
if (user.blocked || user.removed) {
throw new FailException(Response.Status.UNAUTHORIZED, "FAIL Authentiocate"); throw new FailException(Response.Status.UNAUTHORIZED, "FAIL Authentiocate");
} }
return user; return user;
@ -294,12 +313,13 @@ public class UserResource {
@PermitAll @PermitAll
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public GetToken getToken(final DataGetToken data) throws Exception { public GetToken getToken(final DataGetToken data) throws Exception {
LOGGER.info("User Authenticate: {}", data.login()); LOGGER.info("User Authenticate: {}", data.login);
final UserAuth user = checkAuthUser(data.method(), data.login(), data.time(), data.password()); 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. // at the point the user has been not deleted and not blocked.
// this authentication is valid only for Karso ==> not for the application // this authentication is valid only for Karso ==> not for the application
final int expirationTimeInMinutes = ConfigVariable.getAuthExpirationTime(); final int expirationTimeInMinutes = ConfigVariable.getAuthExpirationTime();
// Get the USER Right (Note: by construction KARSO have application ID = KARSO_INITIALISATION_ID // Get the USER Right (Note: by construction KARSO have application ID = KARSO_INITIALISATION_ID
final Map<String, Object> ssoRight = RightResource.getUserRight(user.id, final Map<String, Object> ssoRight = RightResource.getUserRight(user.id,
Initialization.KARSO_INITIALISATION_ID); Initialization.KARSO_INITIALISATION_ID);
@ -309,23 +329,21 @@ public class UserResource {
} }
LOGGER.debug("Get new token with right: {}", ssoRight); LOGGER.debug("Get new token with right: {}", ssoRight);
final Map<String, Object> outRight = new HashMap<>(); final Map<String, Object> outRight = new HashMap<>();
final String applicationName = "karso";
// 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 // 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, ssoRight); outRight.put(UserResource.APPLICATION, ssoRight);
// TODO: maybe correct this get of TTL... // TODO: maybe correct this get of TTL...
final String ret = JWTWrapper.generateJWToken(user.id, user.login, "KarAuth", applicationName, outRight, final String ret = JWTWrapper.generateJWToken(user.id, user.login, "KarAuth", UserResource.APPLICATION,
expirationTimeInMinutes); outRight, expirationTimeInMinutes);
if (ret == null) { if (ret == null) {
throw new SystemException("Missing internal JWT system ==> can not sign anything ..."); throw new SystemException("Missing internal JWT system ==> can not sign anything ...");
} }
// Update last connection: // Update last connection:
final UserAuth newUser = new UserAuth(); final UserAuth newUser = new UserAuth();
newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now()); newUser.lastConnection = Timestamp.valueOf(LocalDateTime.now());
DataAccess.update(newUser, user.id, List.of("lastConnection")); da.update(newUser, user.id, List.of("lastConnection"));
//LOGGER.debug(" ==> generate token: {}", ret);
return new GetToken(ret); return new GetToken(ret);
} }
}
public static String bytesToHex(final byte[] bytes) { public static String bytesToHex(final byte[] bytes) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
@ -335,7 +353,7 @@ public class UserResource {
return sb.toString(); return sb.toString();
} }
public String getSHA512(final String passwordToHash) { public static String getSHA512(final String passwordToHash) {
try { try {
final MessageDigest md = MessageDigest.getInstance("SHA-512"); final MessageDigest md = MessageDigest.getInstance("SHA-512");
final byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8)); final byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));

View File

@ -2,10 +2,13 @@ package org.kar.karso.filter;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.util.Map;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.filter.AuthenticationFilter; import org.kar.archidata.filter.AuthenticationFilter;
import org.kar.archidata.filter.PartRight;
import org.kar.archidata.model.UserByToken; import org.kar.archidata.model.UserByToken;
import org.kar.karso.api.UserResource;
import org.kar.karso.model.ApplicationToken; import org.kar.karso.model.ApplicationToken;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -23,7 +26,7 @@ public class KarsoAuthenticationFilter extends AuthenticationFilter {
//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 //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() { public KarsoAuthenticationFilter() {
super("karso"); super(UserResource.APPLICATION);
} }
@Override @Override
@ -64,7 +67,8 @@ public class KarsoAuthenticationFilter extends AuthenticationFilter {
userByToken.name = value.name; userByToken.name = value.name;
userByToken.parentId = value.parentId; userByToken.parentId = value.parentId;
userByToken.type = UserByToken.TYPE_APPLICATION; userByToken.type = UserByToken.TYPE_APPLICATION;
userByToken.right.put("APPLICATION", true); // TODO: Manage the retrieve of specific rights ...
userByToken.right.put(UserResource.APPLICATION, Map.of("APPLICATION", PartRight.READ_WRITE));
return userByToken; return userByToken;
} }
} }

View File

@ -2,9 +2,10 @@ package org.kar.karso.migration;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
import org.kar.archidata.migration.MigrationSqlStep; import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.tools.UuidUtils; import org.kar.karso.api.UserResource;
import org.kar.karso.model.Application; import org.kar.karso.model.Application;
import org.kar.karso.model.ApplicationToken; import org.kar.karso.model.ApplicationToken;
import org.kar.karso.model.Right; import org.kar.karso.model.Right;
@ -19,62 +20,90 @@ public class Initialization extends MigrationSqlStep {
public static final int KARSO_INITIALISATION_ID = 1; public static final int KARSO_INITIALISATION_ID = 1;
public static final List<Class<?>> LIST_OF_COMMON_CLASSES = List.of(Settings.class, UserAuth.class, public static final List<Class<?>> CLASSES_BASE = List.of(Settings.class, UserAuth.class, Application.class,
Application.class, ApplicationToken.class, RightDescription.class, Right.class); ApplicationToken.class, RightDescription.class, Right.class);
// created object
private Application app = null;
private UserAuth user = null;
private RightDescription rightDescription;
@Override @Override
public String getName() { public String getName() {
return "Initialization"; return "Initialization";
} }
public Initialization() {
}
@Override @Override
public void generateStep() throws Exception { public void generateStep() throws Exception {
for (final Class<?> clazz : LIST_OF_COMMON_CLASSES) { for (final Class<?> clazz : CLASSES_BASE) {
addClass(clazz); addClass(clazz);
} }
addAction( addAction((final DBAccess da) -> {
""" final Application app = new Application();
INSERT INTO `application` (`id`, `name`, `description`, `redirect`, `redirectDev`, `notification`, `ttl`) VALUES //app.id = 1L;
(1, 'karso', 'Root SSO interface', 'http://atria-soft/karso', '', '', 666); app.name = "karso";
"""); app.description = "Root SSO interface";
app.redirect = "https://atria-soft/karso";
app.redirectDev = "http://localhost:4003/karso";
app.notification = "";
app.ttl = 666;
this.app = da.insert(app);
});
// default admin: "karadmin" password: "adminA@666" // default admin: "karadmin" password: "adminA@666"
addAction( addAction((final DBAccess da) -> {
""" final UserAuth user = new UserAuth();
INSERT INTO `user` (`id`, `login`, `password`, `email`, `admin`) VALUES //user.id = 1L;
(1, 'karadmin', '0ddcac5ede3f1300a1ce5948ab15112f2810130531d578ab8bc4dc131652d7cf7a3ff6e827eb957bff43bc2c65a6a1d46722e5b3a2343ac3176a33ea7250080b', user.login = "karadmin";
'admin@admin.ZZZ', 1); user.password = UserResource.getSHA512("adminA@666");
"""); user.email = "admin@admin.ZZZ";
final String data = UuidUtils.nextUUID().toString(); this.user = da.insert(user);
addAction(""" });
INSERT INTO `user_link_application` (`uuid`, `object1Id`, `object2Id`) addAction((final DBAccess da) -> {
VALUES (UUID_TO_BIN('%s'), '1', '1'); AddOnManyToMany.addLink(da, UserAuth.class, this.user.id, "application", this.app.id);
""".formatted(data), "mysql"); });
addAction(""" addAction((final DBAccess da) -> {
INSERT INTO `user_link_application` (`uuid`, `object1Id`, `object2Id`) final Settings settings = new Settings();
VALUES ('%s', '1', '1'); settings.key = "SIGN_UP_ENABLE";
""".formatted(data), "sqlite"); settings.right = "rwr-r-";
addAction(""" settings.type = "BOOLEAN";
INSERT INTO `settings` (`key`, `right`, `type`, `value`) VALUES settings.value = "false";
('SIGN_UP_ENABLE', 'rwr-r-', 'BOOLEAN', 'false'), da.insert(settings);
('SIGN_IN_ENABLE', 'rwr-r-', 'BOOLEAN', 'true'), settings.key = "SIGN_IN_ENABLE";
('SIGN_UP_FILTER', 'rw----', 'STRING', '.*'), settings.right = "rwr-r-";
('EMAIL_VALIDATION_REQUIRED', 'rwr-r-', 'BOOLEAN', 'false'); settings.type = "BOOLEAN";
"""); settings.value = "true";
addAction( da.insert(settings);
""" settings.key = "SIGN_UP_FILTER";
INSERT INTO `rightDescription` (`id`, `applicationId`, `key`, `title`, `description`, `type`, `defaultValue`) VALUES settings.right = "rw----";
(1, 1, 'ADMIN', 'Administrator', 'Full administrator Right', 'BOOLEAN', 'false'); settings.type = "STRING";
"""); settings.value = ".*";
addAction(""" da.insert(settings);
INSERT INTO `right` (`applicationId`, `userId`, `rightDescriptionId`, `value`) VALUES settings.key = "EMAIL_VALIDATION_REQUIRED";
(1, 1, 1, 'true'); settings.right = "rwr-r-";
"""); settings.type = "BOOLEAN";
// we generate an offset to permit to manage some generic upgrade in the future... (can not be done in sqlite) 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";
rightDescription.type = "BOOLEAN";
rightDescription.defaultValue = "false";
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 = "true";
da.insert(right);
});
// we generate an offset to permit to manage some generic upgrade in the future...
addAction(""" addAction("""
ALTER TABLE `application` AUTO_INCREMENT = 1000; ALTER TABLE `application` AUTO_INCREMENT = 1000;
""", "mysql"); """, "mysql");
@ -93,10 +122,10 @@ public class Initialization extends MigrationSqlStep {
display(); display();
} }
public static void dropAll() { public static void dropAll(final DBAccess da) {
for (final Class<?> element : LIST_OF_COMMON_CLASSES) { for (final Class<?> element : CLASSES_BASE) {
try { try {
DataAccess.drop(element); da.drop(element);
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Fail to drop table !!!!!!"); LOGGER.error("Fail to drop table !!!!!!");
ex.printStackTrace(); ex.printStackTrace();
@ -104,10 +133,10 @@ public class Initialization extends MigrationSqlStep {
} }
} }
public static void cleanAll() { public static void cleanAll(final DBAccess da) {
for (final Class<?> element : LIST_OF_COMMON_CLASSES) { for (final Class<?> element : CLASSES_BASE) {
try { try {
DataAccess.cleanAll(element); da.cleanAll(element);
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Fail to clean table !!!!!!"); LOGGER.error("Fail to clean table !!!!!!");
ex.printStackTrace(); ex.printStackTrace();

View File

@ -2,7 +2,7 @@ package org.kar.karso.migration;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.options.AccessDeletedItems; import org.kar.archidata.dataAccess.options.AccessDeletedItems;
import org.kar.archidata.dataAccess.options.OverrideTableName; import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.migration.MigrationSqlStep; import org.kar.archidata.migration.MigrationSqlStep;
@ -28,14 +28,14 @@ public class Migration20240515 extends MigrationSqlStep {
addAction(""" addAction("""
ALTER TABLE `user_link_application` ADD `uuid` binary(16) AFTER `id`; ALTER TABLE `user_link_application` ADD `uuid` binary(16) AFTER `id`;
"""); """);
addAction(() -> { addAction((final DBAccess da) -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), final List<UUIDConversion> datas = da.gets(UUIDConversion.class, new AccessDeletedItems(),
new OverrideTableName("user_link_application")); new OverrideTableName("user_link_application"));
for (final UUIDConversion elem : datas) { for (final UUIDConversion elem : datas) {
elem.uuid = UuidUtils.nextUUID(); elem.uuid = UuidUtils.nextUUID();
} }
for (final UUIDConversion elem : datas) { for (final UUIDConversion elem : datas) {
DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("user_link_application")); da.update(elem, elem.id, List.of("uuid"), new OverrideTableName("user_link_application"));
} }
}); });
addAction(""" addAction("""

View File

@ -1,21 +1,11 @@
package org.kar.karso.model; 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.DataComment;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.model.GenericDataSoftDelete; import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
@ -37,11 +27,11 @@ public class Application extends GenericDataSoftDelete {
@DefaultValue("'http://localhost:4200/sso/notification'") @DefaultValue("'http://localhost:4200/sso/notification'")
public String notification; public String notification;
@Column(nullable = false) @Column(nullable = false)
@DataComment("Expiration time ") @Schema(description = "Expiration time ")
@DefaultValue("666") @DefaultValue("666")
public Integer ttl; public Integer ttl;
@Column(nullable = false) @Column(nullable = false)
@DataComment("Right is manage with Karso") @Schema(description = "Right is manage with Karso")
@DefaultValue("0") @DefaultValue("0")
public Boolean manageRight; public Boolean manageRight;

View File

@ -1,19 +1,39 @@
package org.kar.karso.model; package org.kar.karso.model;
import org.kar.archidata.dataAccess.options.CheckJPA;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.persistence.Column; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class ChangePassword { public class ChangePassword {
@Column(length = 32) @NotNull
@Size(min = 2, max = 2)
@Pattern(regexp = "^v1$")
public String method; public String method;
@Column(length = 512) @NotNull
@Size(min = 3, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9\\-_ \\.@]+$")
public String login; public String login;
@Column(length = 64) @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; public String time;
@Column(length = 128) @NotNull
@Size(min = 128, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
public String password; public String password;
@Column(length = 128) @NotNull
@Size(min = 128, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
public String newPassword; public String newPassword;
public static class ChangePasswordChecker extends CheckJPA<ChangePassword> {
public ChangePasswordChecker() {
super(ChangePassword.class);
}
}
} }

View File

@ -3,21 +3,53 @@ package org.kar.karso.model;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.kar.archidata.dataAccess.options.CheckJPA;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL) import jakarta.validation.constraints.NotNull;
public record DataGetToken( import jakarta.validation.constraints.Pattern;
String login, import jakarta.validation.constraints.Size;
String method,
String time,
String password) {
/*public DataGetToken(String login, String method, @JsonInclude(JsonInclude.Include.NON_NULL)
String time, public class DataGetToken {
String password) { @NotNull
this(login, method, time, password); @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){ public static String sha512(final String passwordToHash) { //, String salt){
String generatedPassword = null; String generatedPassword = null;
@ -36,20 +68,28 @@ public record DataGetToken(
return generatedPassword; 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( public static DataGetToken generate(
final String login, final String login,
final String method, final String password,
final String time, final String time,
final String password) { final String method) {
return generateSha(login, method, time, sha512(password)); return generateSha(login, sha512(password), time, method);
} }
public static DataGetToken generateSha( public static DataGetToken generateSha(
final String login, final String login,
final String method, final String password,
final String time, final String time,
final String password) { final String method) {
return new DataGetToken(login, method, time, return new DataGetToken(login, sha512("login='" + login + "';pass='" + password + "';date='" + time + "'"),
sha512("login='" + login + "';pass='" + password + "';date='" + time + "'")); time, method);
} }
} }

View File

@ -4,6 +4,7 @@ import java.sql.Timestamp;
import java.util.List; import java.util.List;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.dataAccess.options.CheckJPA;
import org.kar.archidata.model.User; import org.kar.archidata.model.User;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@ -12,6 +13,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
@Table(name = "user") @Table(name = "user")
@ -19,6 +22,8 @@ import jakarta.ws.rs.DefaultValue;
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class UserAuth extends User { public class UserAuth extends User {
@Column(length = 128, nullable = false) @Column(length = 128, nullable = false)
@Size(min = 128, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
public String password; public String password;
/* /*
@Column(length = 128) @Column(length = 128)
@ -27,9 +32,13 @@ public class UserAuth extends User {
public String passwordValidation; //!< UniqueId to validate the new password public String passwordValidation; //!< UniqueId to validate the new password
*/ */
@Column(length = 512, nullable = false) @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 String email;
public Timestamp emailValidate; // time of validation public Timestamp emailValidate; // time of validation
@Column(length = 512) @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; public String newEmail;
@DefaultValue("'0'") @DefaultValue("'0'")
@Column(nullable = false) @Column(nullable = false)
@ -38,4 +47,10 @@ public class UserAuth extends User {
@ManyToMany(targetEntity = Application.class) @ManyToMany(targetEntity = Application.class)
public List<Long> applications = null; public List<Long> applications = null;
public static class UserAuthChecker extends CheckJPA<UserAuth> {
public UserAuthChecker() {
super(UserAuth.class);
}
}
} }

View File

@ -1,10 +1,31 @@
package org.kar.karso.model; package org.kar.karso.model;
import org.kar.archidata.dataAccess.options.CheckJPA;
import com.fasterxml.jackson.annotation.JsonInclude; 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) @JsonInclude(JsonInclude.Include.NON_NULL)
public class UserCreate { public class UserCreate {
@NotNull
@Size(min = 3, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9\\-_ \\.@]+$")
public String login; public String login;
@NotNull
@Size(min = 5, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9\\-\\._]+@[a-zA-Z0-9\\-_]+\\.[a-zA-Z0-9]+$")
public String email; public String email;
@NotNull
@Size(min = 128, max = 128)
@Pattern(regexp = "^[a-zA-Z0-9]{128}$")
public String password; public String password;
public static class UserCreateChecker extends CheckJPA<UserCreate> {
public UserCreateChecker() {
super(UserCreate.class);
}
}
} }

View File

@ -0,0 +1,13 @@
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern name="ConversionPattern">
%green(%d{HH:mm:ss.SSS}) %highlight(%-5level) %-30((%file:%line\)): %msg%n
</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -1,35 +0,0 @@
# SLF4J's SimpleLogger configuration file
# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
# Default logging detail level for all instances of SimpleLogger.
# Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, defaults to "info".
org.slf4j.simpleLogger.defaultLogLevel=trace
# Logging detail level for a SimpleLogger instance named "xxxxx".
# Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, the default logging detail level is used.
#org.slf4j.simpleLogger.log.xxxxx=
# Set to true if you want the current date and time to be included in output messages.
# Default is false, and will output the number of milliseconds elapsed since startup.
#org.slf4j.simpleLogger.showDateTime=false
# The date and time format to be used in the output messages.
# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
# If the format is not specified or is invalid, the default format is used.
# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
# Set to true if you want to output the current thread name.
# Defaults to true.
org.slf4j.simpleLogger.showThreadName=true
# Set to true if you want the Logger instance name to be included in output messages.
# Defaults to true.
#org.slf4j.simpleLogger.showLogName=true
# Set to true if you want the last component of the name to be included in output messages.
# Defaults to false.
#org.slf4j.simpleLogger.showShortLogName=false

View File

@ -0,0 +1,126 @@
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();
}
}

View File

@ -11,7 +11,6 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.model.GetToken; import org.kar.archidata.model.GetToken;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.JWTWrapper; import org.kar.archidata.tools.JWTWrapper;
@ -32,8 +31,7 @@ public class TestBase {
public void login(final String login, final String password) { public void login(final String login, final String password) {
try { try {
final GetToken token = api.post(GetToken.class, "users/get_token", final GetToken token = api.post(GetToken.class, "users/get_token", DataGetToken.generate(login, password));
DataGetToken.generate(login, "v1", "202515252", password));
api.setToken(token.jwt); api.setToken(token.jwt);
} catch (final Exception ex) { } catch (final Exception ex) {
Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage()); Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage());
@ -46,15 +44,10 @@ public class TestBase {
@BeforeAll @BeforeAll
public static void configureWebServer() throws Exception { public static void configureWebServer() throws Exception {
ConfigureDb.configure();
LOGGER.info("configure server ..."); LOGGER.info("configure server ...");
webInterface = new WebLauncherTest(); webInterface = new WebLauncherTest();
LOGGER.info("Create DB");
try {
webInterface.migrateDB(); webInterface.migrateDB();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Detect an error: {}", ex.getMessage());
}
LOGGER.info("Start REST (BEGIN)"); LOGGER.info("Start REST (BEGIN)");
webInterface.process(); webInterface.process();
LOGGER.info("Start REST (DONE)"); LOGGER.info("Start REST (DONE)");
@ -66,17 +59,14 @@ public class TestBase {
LOGGER.info("Kill the web server"); LOGGER.info("Kill the web server");
webInterface.stop(); webInterface.stop();
webInterface = null; webInterface = null;
LOGGER.info("Remove the test db"); ConfigureDb.clear();
DBEntry.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
Thread.sleep(1000);
} }
@Order(3) @Order(3)
@Test @Test
public void firstUserConnect() throws Exception { public void firstUserConnect() throws Exception {
final GetToken result = api.post(GetToken.class, "users/get_token", final GetToken result = api.post(GetToken.class, "users/get_token",
DataGetToken.generate("karadmin", "v1", "202515252", "adminA@666")); DataGetToken.generate("karadmin", "adminA@666", "2025-15-25T22:32:23.252Z"));
final String[] splitted = result.jwt.split("\\."); final String[] splitted = result.jwt.split("\\.");
Assertions.assertEquals(3, splitted.length); Assertions.assertEquals(3, splitted.length);
final String authorization = result.jwt; final String authorization = result.jwt;

View File

@ -10,8 +10,7 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.exception.RESTErrorResponseException;
import org.kar.archidata.exception.RESTErrorResponseExeption;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.RESTApi; import org.kar.archidata.tools.RESTApi;
import org.kar.karso.api.HealthCheck.HealthResult; import org.kar.karso.api.HealthCheck.HealthResult;
@ -28,15 +27,10 @@ public class TestHealthCheck {
@BeforeAll @BeforeAll
public static void configureWebServer() throws Exception { public static void configureWebServer() throws Exception {
ConfigureDb.configure();
LOGGER.info("configure server ..."); LOGGER.info("configure server ...");
webInterface = new WebLauncherTest(); webInterface = new WebLauncherTest();
LOGGER.info("Create DB");
try {
webInterface.migrateDB(); webInterface.migrateDB();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Detect an error: {}", ex.getMessage());
}
LOGGER.info("Start REST (BEGIN)"); LOGGER.info("Start REST (BEGIN)");
webInterface.process(); webInterface.process();
LOGGER.info("Start REST (DONE)"); LOGGER.info("Start REST (DONE)");
@ -48,10 +42,7 @@ public class TestHealthCheck {
LOGGER.info("Kill the web server"); LOGGER.info("Kill the web server");
webInterface.stop(); webInterface.stop();
webInterface = null; webInterface = null;
LOGGER.info("Remove the test db"); ConfigureDb.clear();
DBEntry.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
Thread.sleep(1000);
} }
@Order(1) @Order(1)
@ -65,7 +56,7 @@ public class TestHealthCheck {
@Order(2) @Order(2)
@Test @Test
public void checkHealthCheckWrongAPI() throws Exception { public void checkHealthCheckWrongAPI() throws Exception {
Assertions.assertThrows(RESTErrorResponseExeption.class, () -> api.get(HealthResult.class, "health_checks")); Assertions.assertThrows(RESTErrorResponseException.class, () -> api.get(HealthResult.class, "health_checks"));
} }
} }

View File

@ -9,8 +9,7 @@ import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.exception.RESTErrorResponseException;
import org.kar.archidata.exception.RESTErrorResponseExeption;
import org.kar.archidata.model.GetToken; import org.kar.archidata.model.GetToken;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.RESTApi; import org.kar.archidata.tools.RESTApi;
@ -27,8 +26,7 @@ public class TestUnAuthorizedAPI {
public void login(final String login, final String password) { public void login(final String login, final String password) {
try { try {
final GetToken token = api.post(GetToken.class, "users/get_token", final GetToken token = api.post(GetToken.class, "users/get_token", DataGetToken.generate(login, password));
DataGetToken.generate(login, "v1", "202515252", password));
api.setToken(token.jwt); api.setToken(token.jwt);
} catch (final Exception ex) { } catch (final Exception ex) {
Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage()); Assertions.fail("Can not get Authentication for '" + login + "' ==> " + ex.getMessage());
@ -41,15 +39,10 @@ public class TestUnAuthorizedAPI {
@BeforeAll @BeforeAll
public static void configureWebServer() throws Exception { public static void configureWebServer() throws Exception {
ConfigureDb.configure();
LOGGER.info("configure server ..."); LOGGER.info("configure server ...");
webInterface = new WebLauncherTest(); webInterface = new WebLauncherTest();
LOGGER.info("Create DB");
try {
webInterface.migrateDB(); webInterface.migrateDB();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Detect an error: {}", ex.getMessage());
}
LOGGER.info("Start REST (BEGIN)"); LOGGER.info("Start REST (BEGIN)");
webInterface.process(); webInterface.process();
LOGGER.info("Start REST (DONE)"); LOGGER.info("Start REST (DONE)");
@ -61,10 +54,7 @@ public class TestUnAuthorizedAPI {
LOGGER.info("Kill the web server"); LOGGER.info("Kill the web server");
webInterface.stop(); webInterface.stop();
webInterface = null; webInterface = null;
LOGGER.info("Remove the test db"); ConfigureDb.clear();
DBEntry.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
Thread.sleep(1000);
} }
public void checkFail(final String type, final String urlOffset, final int errorStatus) { public void checkFail(final String type, final String urlOffset, final int errorStatus) {
@ -84,7 +74,7 @@ public class TestUnAuthorizedAPI {
api.delete(String.class, urlOffset); api.delete(String.class, urlOffset);
} }
Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'"); Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'");
} catch (final RESTErrorResponseExeption ex) { } catch (final RESTErrorResponseException ex) {
if (errorStatus != ex.status) { if (errorStatus != ex.status) {
LOGGER.error("Fail in test with the wrong return errors: {}", ex.toString()); LOGGER.error("Fail in test with the wrong return errors: {}", ex.toString());
} }
@ -113,7 +103,7 @@ public class TestUnAuthorizedAPI {
api.delete(String.class, urlOffset); api.delete(String.class, urlOffset);
} }
//Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'"); //Assertions.fail("Request on URL does not fail as expected: '" + type + "' url='" + urlOffset + "'");
} catch (final RESTErrorResponseExeption ex) { } catch (final RESTErrorResponseException ex) {
Assertions.fail("Must not fail ... " + ex.toString()); Assertions.fail("Must not fail ... " + ex.toString());
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Unexpected throw error: {}", ex); LOGGER.error("Unexpected throw error: {}", ex);

View File

@ -11,12 +11,10 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.kar.archidata.db.DBEntry; import org.kar.archidata.exception.RESTErrorResponseException;
import org.kar.archidata.exception.RESTErrorResponseExeption;
import org.kar.archidata.model.GetToken; import org.kar.archidata.model.GetToken;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.RESTApi; import org.kar.archidata.tools.RESTApi;
import org.kar.karso.migration.Initialization;
import org.kar.karso.model.DataGetToken; import org.kar.karso.model.DataGetToken;
import org.kar.karso.model.UserAuthGet; import org.kar.karso.model.UserAuthGet;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -34,32 +32,17 @@ public class TestUsers {
private static long idTest; private static long idTest;
@BeforeAll @BeforeAll
public static void configureWebServer() throws InterruptedException, RESTErrorResponseExeption, IOException { public static void configureWebServer() throws Exception {
ConfigureDb.configure();
LOGGER.info("configure server ..."); LOGGER.info("configure server ...");
webInterface = new WebLauncherTest(); webInterface = new WebLauncherTest();
LOGGER.info("Clean previous table");
try {
Initialization.dropAll();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("plop: {}", ex.getLocalizedMessage());
throw ex;
}
LOGGER.info("Create DB");
try {
webInterface.migrateDB(); webInterface.migrateDB();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Detect an error: {}", ex.getMessage());
}
LOGGER.info("Start REST (BEGIN)"); LOGGER.info("Start REST (BEGIN)");
webInterface.process(); webInterface.process();
LOGGER.info("Start REST (DONE)"); LOGGER.info("Start REST (DONE)");
api = new RESTApi(ConfigBaseVariable.apiAdress); api = new RESTApi(ConfigBaseVariable.apiAdress);
final GetToken result = api.post(GetToken.class, "users/get_token", final GetToken result = api.post(GetToken.class, "users/get_token",
DataGetToken.generate("karadmin", "v1", "202515252", "adminA@666")); DataGetToken.generate("karadmin", "adminA@666"));
api.setToken(result.jwt); api.setToken(result.jwt);
} }
@ -68,19 +51,16 @@ public class TestUsers {
LOGGER.info("Kill the web server"); LOGGER.info("Kill the web server");
webInterface.stop(); webInterface.stop();
webInterface = null; webInterface = null;
LOGGER.info("Remove the test db"); ConfigureDb.clear();
DBEntry.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
} }
@Order(1) @Order(1)
@Test @Test
public void getsValue() throws RESTErrorResponseExeption, IOException, InterruptedException { public void getsValue() throws RESTErrorResponseException, IOException, InterruptedException {
final List<UserAuthGet> listUsers = api.gets(UserAuthGet.class, TestUsers.ENDPOINT_NAME); final List<UserAuthGet> listUsers = api.gets(UserAuthGet.class, TestUsers.ENDPOINT_NAME);
Assertions.assertNotNull(listUsers); Assertions.assertNotNull(listUsers);
Assertions.assertEquals(1, listUsers.size()); Assertions.assertEquals(1, listUsers.size());
Assertions.assertEquals(1, listUsers.get(0).id); Assertions.assertEquals(1, listUsers.get(0).id);
Assertions.assertEquals(true, listUsers.get(0).admin);
Assertions.assertEquals(false, listUsers.get(0).blocked); Assertions.assertEquals(false, listUsers.get(0).blocked);
Assertions.assertEquals(false, listUsers.get(0).avatar); Assertions.assertEquals(false, listUsers.get(0).avatar);
Assertions.assertEquals("karadmin", listUsers.get(0).login); Assertions.assertEquals("karadmin", listUsers.get(0).login);