[DEV] remove generic annotation and test json update
This commit is contained in:
parent
f69bc8097a
commit
c4fc49d91b
@ -1,14 +0,0 @@
|
|||||||
package org.kar.archidata.annotation.security;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.NameBinding;
|
|
||||||
|
|
||||||
@NameBinding
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Target({ METHOD })
|
|
||||||
public @interface DenyAll {}
|
|
@ -1,14 +0,0 @@
|
|||||||
package org.kar.archidata.annotation.security;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.NameBinding;
|
|
||||||
|
|
||||||
@NameBinding
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Target({ METHOD })
|
|
||||||
public @interface PermitAll {}
|
|
@ -1,16 +0,0 @@
|
|||||||
package org.kar.archidata.annotation.security;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.NameBinding;
|
|
||||||
|
|
||||||
@NameBinding
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Target({ METHOD })
|
|
||||||
public @interface RolesAllowed {
|
|
||||||
String[] value();
|
|
||||||
}
|
|
@ -22,15 +22,15 @@ import javax.imageio.ImageIO;
|
|||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
import org.kar.archidata.annotation.security.PermitTokenInURI;
|
import org.kar.archidata.annotation.security.PermitTokenInURI;
|
||||||
import org.kar.archidata.annotation.security.RolesAllowed;
|
|
||||||
import org.kar.archidata.dataAccess.QueryCondition;
|
|
||||||
import org.kar.archidata.dataAccess.DataAccess;
|
import org.kar.archidata.dataAccess.DataAccess;
|
||||||
|
import org.kar.archidata.dataAccess.QueryCondition;
|
||||||
import org.kar.archidata.filter.GenericContext;
|
import org.kar.archidata.filter.GenericContext;
|
||||||
import org.kar.archidata.model.Data;
|
import org.kar.archidata.model.Data;
|
||||||
import org.kar.archidata.util.ConfigBaseVariable;
|
import org.kar.archidata.util.ConfigBaseVariable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.Consumes;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.HeaderParam;
|
import jakarta.ws.rs.HeaderParam;
|
||||||
@ -62,7 +62,7 @@ public class DataResource {
|
|||||||
*/
|
*/
|
||||||
private static long tmpFolderId = 1;
|
private static long tmpFolderId = 1;
|
||||||
|
|
||||||
private static void createFolder(String path) throws IOException {
|
private static void createFolder(final String path) throws IOException {
|
||||||
if (!Files.exists(java.nio.file.Path.of(path))) {
|
if (!Files.exists(java.nio.file.Path.of(path))) {
|
||||||
//Log.print("Create folder: " + path);
|
//Log.print("Create folder: " + path);
|
||||||
Files.createDirectories(java.nio.file.Path.of(path));
|
Files.createDirectories(java.nio.file.Path.of(path));
|
||||||
@ -73,89 +73,75 @@ public class DataResource {
|
|||||||
return tmpFolderId++;
|
return tmpFolderId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTmpFileInData(long tmpFolderId) {
|
public static String getTmpFileInData(final long tmpFolderId) {
|
||||||
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId;
|
final String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId;
|
||||||
try {
|
try {
|
||||||
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileData(long tmpFolderId) {
|
public static String getFileData(final long tmpFolderId) {
|
||||||
String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + "data";
|
final String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + "data";
|
||||||
try {
|
try {
|
||||||
createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator);
|
createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator);
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data getWithSha512(String sha512) {
|
public static Data getWithSha512(final String sha512) {
|
||||||
LOGGER.info("find sha512 = {}", sha512);
|
LOGGER.info("find sha512 = {}", sha512);
|
||||||
try {
|
try {
|
||||||
return DataAccess.getWhere(Data.class, new QueryCondition("sha512", "=", sha512));
|
return DataAccess.getWhere(Data.class, new QueryCondition("sha512", "=", sha512));
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data getWithId(long id) {
|
public static Data getWithId(final long id) {
|
||||||
LOGGER.info("find id = {}", id);
|
LOGGER.info("find id = {}", id);
|
||||||
try {
|
try {
|
||||||
return DataAccess.get(Data.class, id);
|
return DataAccess.get(Data.class, id);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data createNewData(long tmpUID, String originalFileName, String sha512) throws IOException {
|
public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) throws IOException {
|
||||||
// determine mime type:
|
// determine mime type:
|
||||||
Data injectedData = new Data();
|
Data injectedData = new Data();
|
||||||
String mimeType = "";
|
String mimeType = "";
|
||||||
String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
|
final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
|
||||||
switch (extension.toLowerCase()) {
|
mimeType = switch (extension.toLowerCase()) {
|
||||||
case "jpg":
|
case "jpg", "jpeg" -> "image/jpeg";
|
||||||
case "jpeg":
|
case "png" -> "image/png";
|
||||||
mimeType = "image/jpeg";
|
case "webp" -> "image/webp";
|
||||||
break;
|
case "mka" -> "audio/x-matroska";
|
||||||
case "png":
|
case "mkv" -> "video/x-matroska";
|
||||||
mimeType = "image/png";
|
case "webm" -> "video/webm";
|
||||||
break;
|
default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'");
|
||||||
case "webp":
|
};
|
||||||
mimeType = "image/webp";
|
|
||||||
break;
|
|
||||||
case "mka":
|
|
||||||
mimeType = "audio/x-matroska";
|
|
||||||
break;
|
|
||||||
case "mkv":
|
|
||||||
mimeType = "video/x-matroska";
|
|
||||||
break;
|
|
||||||
case "webm":
|
|
||||||
mimeType = "video/webm";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IOException("Can not find the mime type of data input: '" + extension + "'");
|
|
||||||
}
|
|
||||||
injectedData.mimeType = mimeType;
|
injectedData.mimeType = mimeType;
|
||||||
injectedData.sha512 = sha512;
|
injectedData.sha512 = sha512;
|
||||||
String tmpPath = getTmpFileInData(tmpUID);
|
final String tmpPath = getTmpFileInData(tmpUID);
|
||||||
injectedData.size = Files.size(Paths.get(tmpPath));
|
injectedData.size = Files.size(Paths.get(tmpPath));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
injectedData = DataAccess.insert(injectedData);
|
injectedData = DataAccess.insert(injectedData);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String mediaPath = getFileData(injectedData.id);
|
final String mediaPath = getFileData(injectedData.id);
|
||||||
LOGGER.info("src = {}", tmpPath);
|
LOGGER.info("src = {}", tmpPath);
|
||||||
LOGGER.info("dst = {}", mediaPath);
|
LOGGER.info("dst = {}", mediaPath);
|
||||||
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
|
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
|
||||||
@ -163,16 +149,16 @@ public class DataResource {
|
|||||||
return injectedData;
|
return injectedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String saveTemporaryFile(InputStream uploadedInputStream, long idData) {
|
public static String saveTemporaryFile(final InputStream uploadedInputStream, final long idData) {
|
||||||
return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData));
|
return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeTemporaryFile(long idData) {
|
public static void removeTemporaryFile(final long idData) {
|
||||||
String filepath = DataResource.getTmpFileInData(idData);
|
final String filepath = DataResource.getTmpFileInData(idData);
|
||||||
if (Files.exists(Paths.get(filepath))) {
|
if (Files.exists(Paths.get(filepath))) {
|
||||||
try {
|
try {
|
||||||
Files.delete(Paths.get(filepath));
|
Files.delete(Paths.get(filepath));
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
LOGGER.info("can not delete temporary file : {}", Paths.get(filepath));
|
LOGGER.info("can not delete temporary file : {}", Paths.get(filepath));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -180,13 +166,13 @@ public class DataResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save uploaded file to a defined location on the server
|
// save uploaded file to a defined location on the server
|
||||||
static String saveFile(InputStream uploadedInputStream, String serverLocation) {
|
static String saveFile(final InputStream uploadedInputStream, final String serverLocation) {
|
||||||
String out = "";
|
String out = "";
|
||||||
try {
|
try {
|
||||||
OutputStream outpuStream = new FileOutputStream(new File(serverLocation));
|
OutputStream outpuStream = new FileOutputStream(new File(serverLocation));
|
||||||
int read = 0;
|
int read = 0;
|
||||||
byte[] bytes = new byte[CHUNK_SIZE_IN];
|
final byte[] bytes = new byte[CHUNK_SIZE_IN];
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
final MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||||
|
|
||||||
outpuStream = new FileOutputStream(new File(serverLocation));
|
outpuStream = new FileOutputStream(new File(serverLocation));
|
||||||
while ((read = uploadedInputStream.read(bytes)) != -1) {
|
while ((read = uploadedInputStream.read(bytes)) != -1) {
|
||||||
@ -199,32 +185,32 @@ public class DataResource {
|
|||||||
outpuStream.flush();
|
outpuStream.flush();
|
||||||
outpuStream.close();
|
outpuStream.close();
|
||||||
// create the end of sha512
|
// create the end of sha512
|
||||||
byte[] sha512Digest = md.digest();
|
final byte[] sha512Digest = md.digest();
|
||||||
// convert in hexadecimal
|
// convert in hexadecimal
|
||||||
out = bytesToHex(sha512Digest);
|
out = bytesToHex(sha512Digest);
|
||||||
uploadedInputStream.close();
|
uploadedInputStream.close();
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
LOGGER.info("Can not write in temporary file ... ");
|
LOGGER.info("Can not write in temporary file ... ");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
} catch (NoSuchAlgorithmException ex) {
|
} catch (final NoSuchAlgorithmException ex) {
|
||||||
LOGGER.info("Can not find sha512 algorithms");
|
LOGGER.info("Can not find sha512 algorithms");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String bytesToHex(byte[] bytes) {
|
public static String bytesToHex(final byte[] bytes) {
|
||||||
StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
for (byte b : bytes) {
|
for (final byte b : bytes) {
|
||||||
sb.append(String.format("%02x", b));
|
sb.append(String.format("%02x", b));
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Data getSmall(Long id) {
|
public Data getSmall(final Long id) {
|
||||||
try {
|
try {
|
||||||
return DataAccess.get(Data.class, id);
|
return DataAccess.get(Data.class, id);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -235,17 +221,17 @@ public class DataResource {
|
|||||||
@Path("/upload/")
|
@Path("/upload/")
|
||||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||||
@RolesAllowed("ADMIN")
|
@RolesAllowed("ADMIN")
|
||||||
public Response uploadFile(@Context SecurityContext sc, @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition fileMetaData) {
|
public Response uploadFile(@Context final SecurityContext sc, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) {
|
||||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||||
LOGGER.info("===================================================");
|
LOGGER.info("===================================================");
|
||||||
LOGGER.info("== DATA uploadFile {}", (gc == null ? "null" : gc.userByToken));
|
LOGGER.info("== DATA uploadFile {}", (gc == null ? "null" : gc.userByToken));
|
||||||
LOGGER.info("===================================================");
|
LOGGER.info("===================================================");
|
||||||
//public NodeSmall uploadFile(final FormDataMultiPart form) {
|
//public NodeSmall uploadFile(final FormDataMultiPart form) {
|
||||||
LOGGER.info("Upload file: ");
|
LOGGER.info("Upload file: ");
|
||||||
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId++;
|
final String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId++;
|
||||||
try {
|
try {
|
||||||
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
saveFile(fileInputStream, filePath);
|
saveFile(fileInputStream, filePath);
|
||||||
@ -258,12 +244,13 @@ public class DataResource {
|
|||||||
@PermitTokenInURI
|
@PermitTokenInURI
|
||||||
@RolesAllowed("USER")
|
@RolesAllowed("USER")
|
||||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
public Response retriveDataId(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id) throws Exception {
|
public Response retriveDataId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range,
|
||||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
@PathParam("id") final Long id) throws Exception {
|
||||||
|
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
LOGGER.info("== DATA retriveDataId ? id={} user={}", id, (gc == null ? "null" : gc.userByToken));
|
LOGGER.info("== DATA retriveDataId ? id={} user={}", id, (gc == null ? "null" : gc.userByToken));
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
Data value = getSmall(id);
|
final Data value = getSmall(id);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
||||||
}
|
}
|
||||||
@ -276,18 +263,18 @@ public class DataResource {
|
|||||||
@PermitTokenInURI
|
@PermitTokenInURI
|
||||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
|
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
|
||||||
public Response retriveDataThumbnailId(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id)
|
public Response retriveDataThumbnailId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range,
|
||||||
throws Exception {
|
@PathParam("id") final Long id) throws Exception {
|
||||||
//GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
//GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
//logger.info("== DATA retriveDataThumbnailId ? {}", (gc==null?"null":gc.user));
|
//logger.info("== DATA retriveDataThumbnailId ? {}", (gc==null?"null":gc.user));
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
Data value = getSmall(id);
|
final Data value = getSmall(id);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
return Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
||||||
}
|
}
|
||||||
String filePathName = ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data";
|
final String filePathName = ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data";
|
||||||
File inputFile = new File(filePathName);
|
final File inputFile = new File(filePathName);
|
||||||
if (!inputFile.exists()) {
|
if (!inputFile.exists()) {
|
||||||
return Response.status(404).entity("{\"error\":\"media Does not exist: " + id + "\"}").type("application/json").build();
|
return Response.status(404).entity("{\"error\":\"media Does not exist: " + id + "\"}").type("application/json").build();
|
||||||
}
|
}
|
||||||
@ -295,31 +282,31 @@ public class DataResource {
|
|||||||
// || value.mimeType.contentEquals("image/webp")
|
// || value.mimeType.contentEquals("image/webp")
|
||||||
) {
|
) {
|
||||||
// reads input image
|
// reads input image
|
||||||
BufferedImage inputImage = ImageIO.read(inputFile);
|
final BufferedImage inputImage = ImageIO.read(inputFile);
|
||||||
int scaledWidth = 250;
|
final int scaledWidth = 250;
|
||||||
int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() * (float) scaledWidth);
|
final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() * scaledWidth);
|
||||||
// creates output image
|
// creates output image
|
||||||
BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType());
|
final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType());
|
||||||
|
|
||||||
// scales the input image to the output image
|
// scales the input image to the output image
|
||||||
Graphics2D g2d = outputImage.createGraphics();
|
final Graphics2D g2d = outputImage.createGraphics();
|
||||||
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
|
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
|
||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
// create the output stream:
|
// create the output stream:
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
// TODO: check how to remove buffer file !!! here, it is not needed at all...
|
// TODO: check how to remove buffer file !!! here, it is not needed at all...
|
||||||
ImageIO.write(outputImage, "JPG", baos);
|
ImageIO.write(outputImage, "JPG", baos);
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain").build();
|
return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain").build();
|
||||||
}
|
}
|
||||||
byte[] imageData = baos.toByteArray();
|
final byte[] imageData = baos.toByteArray();
|
||||||
//Response.ok(new ByteArrayInputStream(imageData)).build();
|
//Response.ok(new ByteArrayInputStream(imageData)).build();
|
||||||
Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, imageData.length);
|
final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, imageData.length);
|
||||||
out.type("image/jpeg");
|
out.type("image/jpeg");
|
||||||
// TODO: move this in a decorator !!!
|
// TODO: move this in a decorator !!!
|
||||||
CacheControl cc = new CacheControl();
|
final CacheControl cc = new CacheControl();
|
||||||
cc.setMaxAge(3600);
|
cc.setMaxAge(3600);
|
||||||
cc.setNoCache(false);
|
cc.setNoCache(false);
|
||||||
out.cacheControl(cc);
|
out.cacheControl(cc);
|
||||||
@ -334,13 +321,13 @@ public class DataResource {
|
|||||||
@PermitTokenInURI
|
@PermitTokenInURI
|
||||||
@RolesAllowed("USER")
|
@RolesAllowed("USER")
|
||||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
public Response retriveDataFull(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id,
|
public Response retriveDataFull(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range,
|
||||||
@PathParam("name") String name) throws Exception {
|
@PathParam("id") final Long id, @PathParam("name") final String name) throws Exception {
|
||||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
final GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
LOGGER.info("== DATA retriveDataFull ? id={} user={}", id, (gc == null ? "null" : gc.userByToken));
|
LOGGER.info("== DATA retriveDataFull ? id={} user={}", id, (gc == null ? "null" : gc.userByToken));
|
||||||
//logger.info("===================================================");
|
//logger.info("===================================================");
|
||||||
Data value = getSmall(id);
|
final Data value = getSmall(id);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
Response.status(404).entity("media NOT FOUND: " + id).type("text/plain").build();
|
||||||
}
|
}
|
||||||
@ -354,33 +341,33 @@ public class DataResource {
|
|||||||
* @return Streaming output
|
* @return Streaming output
|
||||||
* @throws Exception IOException if an error occurs in streaming.
|
* @throws Exception IOException if an error occurs in streaming.
|
||||||
*/
|
*/
|
||||||
private Response buildStream(final String filename, final String range, String mimeType) throws Exception {
|
private Response buildStream(final String filename, final String range, final String mimeType) throws Exception {
|
||||||
File file = new File(filename);
|
final File file = new File(filename);
|
||||||
//logger.info("request range : {}", range);
|
//logger.info("request range : {}", range);
|
||||||
// range not requested : Firefox does not send range headers
|
// range not requested : Firefox does not send range headers
|
||||||
if (range == null) {
|
if (range == null) {
|
||||||
final StreamingOutput output = new StreamingOutput() {
|
final StreamingOutput output = new StreamingOutput() {
|
||||||
@Override
|
@Override
|
||||||
public void write(OutputStream out) {
|
public void write(final OutputStream out) {
|
||||||
try (FileInputStream in = new FileInputStream(file)) {
|
try (FileInputStream in = new FileInputStream(file)) {
|
||||||
byte[] buf = new byte[1024 * 1024];
|
final byte[] buf = new byte[1024 * 1024];
|
||||||
int len;
|
int len;
|
||||||
while ((len = in.read(buf)) != -1) {
|
while ((len = in.read(buf)) != -1) {
|
||||||
try {
|
try {
|
||||||
out.write(buf, 0, len);
|
out.write(buf, 0, len);
|
||||||
out.flush();
|
out.flush();
|
||||||
//logger.info("---- wrote {} bytes file ----", len);
|
//logger.info("---- wrote {} bytes file ----", len);
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
LOGGER.info("remote close connection");
|
LOGGER.info("remote close connection");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
throw new InternalServerErrorException(ex);
|
throw new InternalServerErrorException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Response.ResponseBuilder out = Response.ok(output).header(HttpHeaders.CONTENT_LENGTH, file.length());
|
final Response.ResponseBuilder out = Response.ok(output).header(HttpHeaders.CONTENT_LENGTH, file.length());
|
||||||
if (mimeType != null) {
|
if (mimeType != null) {
|
||||||
out.type(mimeType);
|
out.type(mimeType);
|
||||||
}
|
}
|
||||||
@ -388,7 +375,7 @@ public class DataResource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] ranges = range.split("=")[1].split("-");
|
final String[] ranges = range.split("=")[1].split("-");
|
||||||
final long from = Long.parseLong(ranges[0]);
|
final long from = Long.parseLong(ranges[0]);
|
||||||
|
|
||||||
//logger.info("request range : {}", ranges.length);
|
//logger.info("request range : {}", ranges.length);
|
||||||
@ -396,10 +383,8 @@ public class DataResource {
|
|||||||
long to = CHUNK_SIZE + from;
|
long to = CHUNK_SIZE + from;
|
||||||
if (ranges.length == 1) {
|
if (ranges.length == 1) {
|
||||||
to = file.length() - 1;
|
to = file.length() - 1;
|
||||||
} else {
|
} else if (to >= file.length()) {
|
||||||
if (to >= file.length()) {
|
to = file.length() - 1;
|
||||||
to = (long) (file.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length());
|
final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length());
|
||||||
//logger.info("responseRange: {}", responseRange);
|
//logger.info("responseRange: {}", responseRange);
|
||||||
@ -408,7 +393,7 @@ public class DataResource {
|
|||||||
|
|
||||||
final long len = to - from + 1;
|
final long len = to - from + 1;
|
||||||
final MediaStreamer streamer = new MediaStreamer(len, raf);
|
final MediaStreamer streamer = new MediaStreamer(len, raf);
|
||||||
Response.ResponseBuilder out = Response.ok(streamer).status(Response.Status.PARTIAL_CONTENT).header("Accept-Ranges", "bytes").header("Content-Range", responseRange)
|
final Response.ResponseBuilder out = Response.ok(streamer).status(Response.Status.PARTIAL_CONTENT).header("Accept-Ranges", "bytes").header("Content-Range", responseRange)
|
||||||
.header(HttpHeaders.CONTENT_LENGTH, streamer.getLenth()).header(HttpHeaders.LAST_MODIFIED, new Date(file.lastModified()));
|
.header(HttpHeaders.CONTENT_LENGTH, streamer.getLenth()).header(HttpHeaders.LAST_MODIFIED, new Date(file.lastModified()));
|
||||||
if (mimeType != null) {
|
if (mimeType != null) {
|
||||||
out.type(mimeType);
|
out.type(mimeType);
|
||||||
@ -416,7 +401,7 @@ public class DataResource {
|
|||||||
return out.build();
|
return out.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void undelete(Long id) throws Exception {
|
public static void undelete(final Long id) throws Exception {
|
||||||
DataAccess.unsetDelete(Data.class, id);
|
DataAccess.unsetDelete(Data.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ package org.kar.archidata.api;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.kar.archidata.annotation.security.PermitAll;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
import jakarta.ws.rs.NotFoundException;
|
import jakarta.ws.rs.NotFoundException;
|
||||||
import jakarta.ws.rs.NotSupportedException;
|
import jakarta.ws.rs.NotSupportedException;
|
||||||
@ -22,16 +22,16 @@ public class FrontGeneric {
|
|||||||
|
|
||||||
protected String baseFrontFolder = "/data/front";
|
protected String baseFrontFolder = "/data/front";
|
||||||
|
|
||||||
private String getExtension(String filename) {
|
private String getExtension(final String filename) {
|
||||||
if (filename.contains(".")) {
|
if (filename.contains(".")) {
|
||||||
return filename.substring(filename.lastIndexOf(".") + 1);
|
return filename.substring(filename.lastIndexOf(".") + 1);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response retrive(String fileName) throws Exception {
|
private Response retrive(final String fileName) throws Exception {
|
||||||
String filePathName = baseFrontFolder + File.separator + fileName;
|
String filePathName = this.baseFrontFolder + File.separator + fileName;
|
||||||
String extention = getExtension(filePathName);
|
final String extention = getExtension(filePathName);
|
||||||
String mineType = null;
|
String mineType = null;
|
||||||
LOGGER.debug("try retrive : '{}' '{}'", filePathName, extention);
|
LOGGER.debug("try retrive : '{}' '{}'", filePathName, extention);
|
||||||
if (extention.length() != 0 && extention.length() <= 5) {
|
if (extention.length() != 0 && extention.length() <= 5) {
|
||||||
@ -66,18 +66,18 @@ public class FrontGeneric {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mineType = "text/html";
|
mineType = "text/html";
|
||||||
filePathName = baseFrontFolder + File.separator + "index.html";
|
filePathName = this.baseFrontFolder + File.separator + "index.html";
|
||||||
}
|
}
|
||||||
LOGGER.debug(" ==> '[}'", filePathName);
|
LOGGER.debug(" ==> '[}'", filePathName);
|
||||||
// reads input image
|
// reads input image
|
||||||
File download = new File(filePathName);
|
final File download = new File(filePathName);
|
||||||
if (!download.exists()) {
|
if (!download.exists()) {
|
||||||
throw new NotFoundException("Not Found: '" + fileName + "' extension='" + extention + "'");
|
throw new NotFoundException("Not Found: '" + fileName + "' extension='" + extention + "'");
|
||||||
}
|
}
|
||||||
ResponseBuilder response = Response.ok((Object) download);
|
final ResponseBuilder response = Response.ok(download);
|
||||||
// use this if I want to download the file:
|
// use this if I want to download the file:
|
||||||
//response.header("Content-Disposition", "attachment; filename=" + fileName);
|
//response.header("Content-Disposition", "attachment; filename=" + fileName);
|
||||||
CacheControl cc = new CacheControl();
|
final CacheControl cc = new CacheControl();
|
||||||
cc.setMaxAge(60);
|
cc.setMaxAge(60);
|
||||||
cc.setNoCache(false);
|
cc.setNoCache(false);
|
||||||
response.cacheControl(cc);
|
response.cacheControl(cc);
|
||||||
@ -99,9 +99,9 @@ public class FrontGeneric {
|
|||||||
@PermitAll()
|
@PermitAll()
|
||||||
//@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
//@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
|
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
|
||||||
public Response retrive1(@PathParam("any") List<PathSegment> segments) throws Exception {
|
public Response retrive1(@PathParam("any") final List<PathSegment> segments) throws Exception {
|
||||||
String filename = "";
|
String filename = "";
|
||||||
for (PathSegment elem : segments) {
|
for (final PathSegment elem : segments) {
|
||||||
if (!filename.isEmpty()) {
|
if (!filename.isEmpty()) {
|
||||||
filename += File.separator;
|
filename += File.separator;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,11 @@ import jakarta.ws.rs.core.StreamingOutput;
|
|||||||
public class MediaStreamer implements StreamingOutput {
|
public class MediaStreamer implements StreamingOutput {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MediaStreamer.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(MediaStreamer.class);
|
||||||
private final int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
|
private final int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
|
||||||
final byte[] buf = new byte[CHUNK_SIZE];
|
final byte[] buf = new byte[this.CHUNK_SIZE];
|
||||||
private long length;
|
private long length;
|
||||||
private RandomAccessFile raf;
|
private final RandomAccessFile raf;
|
||||||
|
|
||||||
public MediaStreamer(long length, RandomAccessFile raf) throws IOException {
|
public MediaStreamer(final long length, final RandomAccessFile raf) throws IOException {
|
||||||
//logger.info("request stream of {} data", length / 1024);
|
//logger.info("request stream of {} data", length / 1024);
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
throw new IOException("Wrong size of the file to stream: " + length);
|
throw new IOException("Wrong size of the file to stream: " + length);
|
||||||
@ -28,26 +28,26 @@ public class MediaStreamer implements StreamingOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(OutputStream outputStream) {
|
public void write(final OutputStream outputStream) {
|
||||||
try {
|
try {
|
||||||
while (length != 0) {
|
while (this.length != 0) {
|
||||||
int read = raf.read(buf, 0, buf.length > length ? (int) length : buf.length);
|
final int read = this.raf.read(this.buf, 0, this.buf.length > this.length ? (int) this.length : this.buf.length);
|
||||||
try {
|
try {
|
||||||
outputStream.write(buf, 0, read);
|
outputStream.write(this.buf, 0, read);
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
LOGGER.info("remote close connection");
|
LOGGER.info("remote close connection");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
length -= read;
|
this.length -= read;
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
throw new InternalServerErrorException(ex);
|
throw new InternalServerErrorException(ex);
|
||||||
} catch (WebApplicationException ex) {
|
} catch (final WebApplicationException ex) {
|
||||||
throw new InternalServerErrorException(ex);
|
throw new InternalServerErrorException(ex);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
raf.close();
|
this.raf.close();
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
throw new InternalServerErrorException(ex);
|
throw new InternalServerErrorException(ex);
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ public class MediaStreamer implements StreamingOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getLenth() {
|
public long getLenth() {
|
||||||
return length;
|
return this.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -623,7 +623,7 @@ public class DataAccess {
|
|||||||
// check the compatibility of the id and the declared ID
|
// check the compatibility of the id and the declared ID
|
||||||
final Class<?> typeClass = idField.getType();
|
final Class<?> typeClass = idField.getType();
|
||||||
if (id == typeClass) {
|
if (id == typeClass) {
|
||||||
throw new Exception("Request update with the wriong type ...");
|
throw new Exception("Request update with the wrong type ...");
|
||||||
}
|
}
|
||||||
// Udpade Json Value
|
// Udpade Json Value
|
||||||
return updateWithJson(clazz, new QueryCondition(AnnotationTools.getFieldName(idField), "=", id), jsonData);
|
return updateWithJson(clazz, new QueryCondition(AnnotationTools.getFieldName(idField), "=", id), jsonData);
|
||||||
@ -638,15 +638,15 @@ public class DataAccess {
|
|||||||
final List<String> keys = new ArrayList<>();
|
final List<String> keys = new ArrayList<>();
|
||||||
final var iterator = root.fieldNames();
|
final var iterator = root.fieldNames();
|
||||||
iterator.forEachRemaining(e -> keys.add(e));
|
iterator.forEachRemaining(e -> keys.add(e));
|
||||||
return update(data, condition, keys);
|
return updateWhere(data, condition, null, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T, ID_TYPE> int update(final T data, final ID_TYPE id) throws Exception {
|
public static <T, ID_TYPE> int update(final T data, final ID_TYPE id) throws Exception {
|
||||||
return update(data, id, null);
|
return update(data, id, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> int update(final T data, final QueryItem condition) throws Exception {
|
public static <T> int updateWhere(final T data, final QueryItem condition) throws Exception {
|
||||||
return update(data, condition, null);
|
return updateWhere(data, condition, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,10 +10,7 @@ import java.util.Map.Entry;
|
|||||||
// https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey/45814178#45814178
|
// https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey/45814178#45814178
|
||||||
// https://stackoverflow.com/questions/32817210/how-to-access-jersey-resource-secured-by-rolesallowed
|
// https://stackoverflow.com/questions/32817210/how-to-access-jersey-resource-secured-by-rolesallowed
|
||||||
|
|
||||||
import org.kar.archidata.annotation.security.DenyAll;
|
|
||||||
import org.kar.archidata.annotation.security.PermitAll;
|
|
||||||
import org.kar.archidata.annotation.security.PermitTokenInURI;
|
import org.kar.archidata.annotation.security.PermitTokenInURI;
|
||||||
import org.kar.archidata.annotation.security.RolesAllowed;
|
|
||||||
import org.kar.archidata.catcher.RestErrorResponse;
|
import org.kar.archidata.catcher.RestErrorResponse;
|
||||||
import org.kar.archidata.model.UserByToken;
|
import org.kar.archidata.model.UserByToken;
|
||||||
import org.kar.archidata.util.JWTWrapper;
|
import org.kar.archidata.util.JWTWrapper;
|
||||||
@ -23,6 +20,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
import com.nimbusds.jwt.JWTClaimsSet;
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
|
|
||||||
import jakarta.annotation.Priority;
|
import jakarta.annotation.Priority;
|
||||||
|
import jakarta.annotation.security.DenyAll;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import jakarta.ws.rs.Priorities;
|
import jakarta.ws.rs.Priorities;
|
||||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||||
import jakarta.ws.rs.container.ContainerRequestFilter;
|
import jakarta.ws.rs.container.ContainerRequestFilter;
|
||||||
@ -46,23 +46,22 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
private static final String AUTHENTICATION_SCHEME = "Yota";
|
private static final String AUTHENTICATION_SCHEME = "Yota";
|
||||||
private static final String AUTHENTICATION_TOKEN_SCHEME = "Zota";
|
private static final String AUTHENTICATION_TOKEN_SCHEME = "Zota";
|
||||||
|
|
||||||
public AuthenticationFilter(String applicationName) {
|
public AuthenticationFilter(final String applicationName) {
|
||||||
super();
|
|
||||||
this.applicationName = applicationName;
|
this.applicationName = applicationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(ContainerRequestContext requestContext) throws IOException {
|
public void filter(final ContainerRequestContext requestContext) throws IOException {
|
||||||
/*
|
/*
|
||||||
logger.debug("-----------------------------------------------------");
|
logger.debug("-----------------------------------------------------");
|
||||||
logger.debug("---- Check if have authorization ----");
|
logger.debug("---- Check if have authorization ----");
|
||||||
logger.debug("-----------------------------------------------------");
|
logger.debug("-----------------------------------------------------");
|
||||||
logger.debug(" for:{}", requestContext.getUriInfo().getPath());
|
logger.debug(" for:{}", requestContext.getUriInfo().getPath());
|
||||||
*/
|
*/
|
||||||
Method method = resourceInfo.getResourceMethod();
|
final Method method = this.resourceInfo.getResourceMethod();
|
||||||
// Access denied for all
|
// Access denied for all
|
||||||
if (method.isAnnotationPresent(DenyAll.class)) {
|
if (method.isAnnotationPresent(DenyAll.class)) {
|
||||||
logger.debug(" ==> deny all {}", requestContext.getUriInfo().getPath());
|
this.logger.debug(" ==> deny all {}", requestContext.getUriInfo().getPath());
|
||||||
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access blocked !!!").build());
|
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access blocked !!!").build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -75,7 +74,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
}
|
}
|
||||||
// this is a security guard, all the API must define their access level:
|
// this is a security guard, all the API must define their access level:
|
||||||
if (!method.isAnnotationPresent(RolesAllowed.class)) {
|
if (!method.isAnnotationPresent(RolesAllowed.class)) {
|
||||||
logger.error(" ==> missing @RolesAllowed {}", requestContext.getUriInfo().getPath());
|
this.logger.error(" ==> missing @RolesAllowed {}", requestContext.getUriInfo().getPath());
|
||||||
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access ILLEGAL !!!").build());
|
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access ILLEGAL !!!").build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -84,8 +83,8 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
|
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
|
||||||
//logger.debug("authorizationHeader: {}", authorizationHeader);
|
//logger.debug("authorizationHeader: {}", authorizationHeader);
|
||||||
if (authorizationHeader == null && method.isAnnotationPresent(PermitTokenInURI.class)) {
|
if (authorizationHeader == null && method.isAnnotationPresent(PermitTokenInURI.class)) {
|
||||||
MultivaluedMap<String, String> quaryparam = requestContext.getUriInfo().getQueryParameters();
|
final MultivaluedMap<String, String> quaryparam = requestContext.getUriInfo().getQueryParameters();
|
||||||
for (Entry<String, List<String>> item : quaryparam.entrySet()) {
|
for (final Entry<String, List<String>> item : quaryparam.entrySet()) {
|
||||||
if (item.getKey().equals(HttpHeaders.AUTHORIZATION)) {
|
if (item.getKey().equals(HttpHeaders.AUTHORIZATION)) {
|
||||||
if (!item.getValue().isEmpty()) {
|
if (!item.getValue().isEmpty()) {
|
||||||
authorizationHeader = item.getValue().get(0);
|
authorizationHeader = item.getValue().get(0);
|
||||||
@ -95,58 +94,58 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// logger.debug("authorizationHeader: {}", authorizationHeader);
|
// logger.debug("authorizationHeader: {}", authorizationHeader);
|
||||||
boolean isApplicationToken = isApplicationTokenBasedAuthentication(authorizationHeader);
|
final boolean isApplicationToken = isApplicationTokenBasedAuthentication(authorizationHeader);
|
||||||
boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader);
|
final boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader);
|
||||||
// Validate the Authorization header data Model "Yota jwt.to.ken" "Zota tokenId:hash(token)"
|
// Validate the Authorization header data Model "Yota jwt.to.ken" "Zota tokenId:hash(token)"
|
||||||
if (!isApplicationToken && !isJwtToken) {
|
if (!isApplicationToken && !isJwtToken) {
|
||||||
logger.warn("REJECTED unauthorized: {}", requestContext.getUriInfo().getPath());
|
this.logger.warn("REJECTED unauthorized: {}", requestContext.getUriInfo().getPath());
|
||||||
abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath());
|
abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UserByToken userByToken = null;
|
UserByToken userByToken = null;
|
||||||
if (isJwtToken) {
|
if (isJwtToken) {
|
||||||
// Extract the token from the Authorization header (Remove "Yota ")
|
// Extract the token from the Authorization header (Remove "Yota ")
|
||||||
String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
|
final String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
|
||||||
//logger.debug("token: {}", token);
|
//logger.debug("token: {}", token);
|
||||||
try {
|
try {
|
||||||
userByToken = validateJwtToken(token);
|
userByToken = validateJwtToken(token);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
logger.error("Fail to validate token: {}", e.getMessage());
|
this.logger.error("Fail to validate token: {}", e.getMessage());
|
||||||
abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage());
|
abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (userByToken == null) {
|
if (userByToken == null) {
|
||||||
logger.warn("get a NULL user ...");
|
this.logger.warn("get a NULL user ...");
|
||||||
abortWithUnauthorized(requestContext, "get a NULL user ...");
|
abortWithUnauthorized(requestContext, "get a NULL user ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Extract the token from the Authorization header (Remove "Zota ")
|
// Extract the token from the Authorization header (Remove "Zota ")
|
||||||
String token = authorizationHeader.substring(AUTHENTICATION_TOKEN_SCHEME.length()).trim();
|
final String token = authorizationHeader.substring(AUTHENTICATION_TOKEN_SCHEME.length()).trim();
|
||||||
//logger.debug("token: {}", token);
|
//logger.debug("token: {}", token);
|
||||||
try {
|
try {
|
||||||
userByToken = validateToken(token);
|
userByToken = validateToken(token);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
logger.error("Fail to validate token: {}", e.getMessage());
|
this.logger.error("Fail to validate token: {}", e.getMessage());
|
||||||
abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage());
|
abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (userByToken == null) {
|
if (userByToken == null) {
|
||||||
logger.warn("get a NULL application ...");
|
this.logger.warn("get a NULL application ...");
|
||||||
abortWithUnauthorized(requestContext, "get a NULL application ...");
|
abortWithUnauthorized(requestContext, "get a NULL application ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// create the security context model:
|
// create the security context model:
|
||||||
String scheme = requestContext.getUriInfo().getRequestUri().getScheme();
|
final String scheme = requestContext.getUriInfo().getRequestUri().getScheme();
|
||||||
MySecurityContext userContext = new MySecurityContext(userByToken, scheme);
|
final MySecurityContext userContext = new MySecurityContext(userByToken, scheme);
|
||||||
// retrieve the allowed right:
|
// retrieve the allowed right:
|
||||||
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
|
final RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
|
||||||
List<String> roles = Arrays.asList(rolesAnnotation.value());
|
final List<String> roles = Arrays.asList(rolesAnnotation.value());
|
||||||
// check if the user have the right:
|
// check if the user have the right:
|
||||||
boolean haveRight = false;
|
boolean haveRight = false;
|
||||||
for (String role : roles) {
|
for (final String role : roles) {
|
||||||
if (userContext.isUserInRole(role)) {
|
if (userContext.isUserInRole(role)) {
|
||||||
haveRight = true;
|
haveRight = true;
|
||||||
break;
|
break;
|
||||||
@ -154,7 +153,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
}
|
}
|
||||||
//Is user valid?
|
//Is user valid?
|
||||||
if (!haveRight) {
|
if (!haveRight) {
|
||||||
logger.error("REJECTED not enought right : {} require: {}", requestContext.getUriInfo().getPath(), roles);
|
this.logger.error("REJECTED not enought right : {} require: {}", requestContext.getUriInfo().getPath(), roles);
|
||||||
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Not enought RIGHT !!!").build());
|
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Not enought RIGHT !!!").build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -162,59 +161,59 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
|||||||
// logger.debug("Get local user : {} / {}", user, userByToken);
|
// logger.debug("Get local user : {} / {}", user, userByToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTokenBasedAuthentication(String authorizationHeader) {
|
private boolean isTokenBasedAuthentication(final String authorizationHeader) {
|
||||||
// Check if the Authorization header is valid
|
// Check if the Authorization header is valid
|
||||||
// It must not be null and must be prefixed with "Bearer" plus a whitespace
|
// It must not be null and must be prefixed with "Bearer" plus a whitespace
|
||||||
// The authentication scheme comparison must be case-insensitive
|
// The authentication scheme comparison must be case-insensitive
|
||||||
return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
|
return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isApplicationTokenBasedAuthentication(String authorizationHeader) {
|
private boolean isApplicationTokenBasedAuthentication(final String authorizationHeader) {
|
||||||
// Check if the Authorization header is valid
|
// Check if the Authorization header is valid
|
||||||
// It must not be null and must be prefixed with "Bearer" plus a whitespace
|
// It must not be null and must be prefixed with "Bearer" plus a whitespace
|
||||||
// The authentication scheme comparison must be case-insensitive
|
// The authentication scheme comparison must be case-insensitive
|
||||||
return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_TOKEN_SCHEME.toLowerCase() + " ");
|
return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_TOKEN_SCHEME.toLowerCase() + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void abortWithUnauthorized(ContainerRequestContext requestContext, String message) {
|
private void abortWithUnauthorized(final ContainerRequestContext requestContext, final String message) {
|
||||||
|
|
||||||
// Abort the filter chain with a 401 status code response
|
// Abort the filter chain with a 401 status code response
|
||||||
// The WWW-Authenticate header is sent along with the response
|
// The WWW-Authenticate header is sent along with the response
|
||||||
logger.warn("abortWithUnauthorized:");
|
this.logger.warn("abortWithUnauthorized:");
|
||||||
RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message);
|
final RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message);
|
||||||
logger.error("Error UUID={}", ret.uuid);
|
this.logger.error("Error UUID={}", ret.uuid);
|
||||||
requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)").entity(ret)
|
requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)").entity(ret)
|
||||||
.type(MediaType.APPLICATION_JSON).build());
|
.type(MediaType.APPLICATION_JSON).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UserByToken validateToken(String authorization) throws Exception {
|
protected UserByToken validateToken(final String authorization) throws Exception {
|
||||||
logger.info("Must be Override by the application implmentation, otherwise it dose not work");
|
this.logger.info("Must be Override by the application implmentation, otherwise it dose not work");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be override to be good implementation
|
// must be override to be good implementation
|
||||||
protected UserByToken validateJwtToken(String authorization) throws Exception {
|
protected UserByToken validateJwtToken(final String authorization) throws Exception {
|
||||||
//logger.debug(" validate token : " + authorization);
|
//logger.debug(" validate token : " + authorization);
|
||||||
JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null);
|
final JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null);
|
||||||
// check the token is valid !!! (signed and coherent issuer...
|
// check the token is valid !!! (signed and coherent issuer...
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
logger.error("The token is not valid: '{}'", authorization);
|
this.logger.error("The token is not valid: '{}'", authorization);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// check userID
|
// check userID
|
||||||
String userUID = ret.getSubject();
|
final String userUID = ret.getSubject();
|
||||||
long id = Long.parseLong(userUID);
|
final long id = Long.parseLong(userUID);
|
||||||
UserByToken user = new UserByToken();
|
final UserByToken user = new UserByToken();
|
||||||
user.id = id;
|
user.id = id;
|
||||||
user.name = (String) ret.getClaim("login");
|
user.name = (String) ret.getClaim("login");
|
||||||
user.type = UserByToken.TYPE_USER;
|
user.type = UserByToken.TYPE_USER;
|
||||||
Object rowRight = ret.getClaim("right");
|
final Object rowRight = ret.getClaim("right");
|
||||||
if (rowRight != null) {
|
if (rowRight != null) {
|
||||||
Map<String, Map<String, Object>> rights = (Map<String, Map<String, Object>>) ret.getClaim("right");
|
final Map<String, Map<String, Object>> rights = (Map<String, Map<String, Object>>) ret.getClaim("right");
|
||||||
if (rights.containsKey(this.applicationName)) {
|
if (rights.containsKey(this.applicationName)) {
|
||||||
user.right = rights.get(this.applicationName);
|
user.right = rights.get(this.applicationName);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Connect with no right for this application='{}' full Right='{}'", this.applicationName, rights);
|
this.logger.error("Connect with no right for this application='{}' full Right='{}'", this.applicationName, rights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//logger.debug("request user: '{}' right: '{}' row='{}'", userUID, user.right, rowRight);
|
//logger.debug("request user: '{}' right: '{}' row='{}'", userUID, user.right, rowRight);
|
||||||
|
@ -4,6 +4,4 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
|||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public record GetToken(
|
public record GetToken(
|
||||||
String jwt) {
|
String jwt) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -13,6 +13,7 @@ public class ConfigBaseVariable {
|
|||||||
static public String apiAdress;
|
static public String apiAdress;
|
||||||
static public String ssoAdress;
|
static public String ssoAdress;
|
||||||
static public String ssoToken;
|
static public String ssoToken;
|
||||||
|
static public String testMode;
|
||||||
|
|
||||||
// For test only
|
// For test only
|
||||||
public static void clearAllValue() {
|
public static void clearAllValue() {
|
||||||
@ -28,6 +29,7 @@ public class ConfigBaseVariable {
|
|||||||
apiAdress = System.getenv("API_ADDRESS");
|
apiAdress = System.getenv("API_ADDRESS");
|
||||||
ssoAdress = System.getenv("SSO_ADDRESS");
|
ssoAdress = System.getenv("SSO_ADDRESS");
|
||||||
ssoToken = System.getenv("SSO_TOKEN");
|
ssoToken = System.getenv("SSO_TOKEN");
|
||||||
|
testMode = System.getenv("TEST_MODE");
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -111,4 +113,11 @@ public class ConfigBaseVariable {
|
|||||||
public static String ssoToken() {
|
public static String ssoToken() {
|
||||||
return ssoToken;
|
return ssoToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getTestMode() {
|
||||||
|
if (testMode == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Boolean.parseBoolean(testMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import java.net.URL;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -18,17 +19,57 @@ import com.nimbusds.jose.JOSEException;
|
|||||||
import com.nimbusds.jose.JOSEObjectType;
|
import com.nimbusds.jose.JOSEObjectType;
|
||||||
import com.nimbusds.jose.JWSAlgorithm;
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
import com.nimbusds.jose.JWSHeader;
|
import com.nimbusds.jose.JWSHeader;
|
||||||
|
import com.nimbusds.jose.JWSObject;
|
||||||
import com.nimbusds.jose.JWSSigner;
|
import com.nimbusds.jose.JWSSigner;
|
||||||
import com.nimbusds.jose.JWSVerifier;
|
import com.nimbusds.jose.JWSVerifier;
|
||||||
import com.nimbusds.jose.crypto.RSASSASigner;
|
import com.nimbusds.jose.crypto.RSASSASigner;
|
||||||
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
||||||
|
import com.nimbusds.jose.jca.JCAContext;
|
||||||
import com.nimbusds.jose.jwk.RSAKey;
|
import com.nimbusds.jose.jwk.RSAKey;
|
||||||
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
|
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
|
||||||
|
import com.nimbusds.jose.util.Base64URL;
|
||||||
import com.nimbusds.jwt.JWTClaimsSet;
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
class TestSigner implements JWSSigner {
|
||||||
|
public static String test_signature = "TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the specified {@link JWSObject#getSigningInput input} of a
|
||||||
|
* {@link JWSObject JWS object}.
|
||||||
|
*
|
||||||
|
* @param header The JSON Web Signature (JWS) header. Must
|
||||||
|
* specify a supported JWS algorithm and must not
|
||||||
|
* be {@code null}.
|
||||||
|
* @param signingInput The input to sign. Must not be {@code null}.
|
||||||
|
*
|
||||||
|
* @return The resulting signature part (third part) of the JWS object.
|
||||||
|
*
|
||||||
|
* @throws JOSEException If the JWS algorithm is not supported, if a
|
||||||
|
* critical header parameter is not supported or
|
||||||
|
* marked for deferral to the application, or if
|
||||||
|
* signing failed for some other internal reason.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Base64URL sign(final JWSHeader header, final byte[] signingInput) throws JOSEException {
|
||||||
|
return new Base64URL(test_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<JWSAlgorithm> supportedJWSAlgorithms() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JCAContext getJCAContext() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class JWTWrapper {
|
public class JWTWrapper {
|
||||||
static final Logger logger = LoggerFactory.getLogger(JWTWrapper.class);
|
static final Logger LOGGER = LoggerFactory.getLogger(JWTWrapper.class);
|
||||||
|
|
||||||
private static RSAKey rsaJWK = null;;
|
private static RSAKey rsaJWK = null;;
|
||||||
private static RSAKey rsaPublicJWK = null;
|
private static RSAKey rsaPublicJWK = null;
|
||||||
@ -36,79 +77,79 @@ public class JWTWrapper {
|
|||||||
public static class PublicKey {
|
public static class PublicKey {
|
||||||
public String key;
|
public String key;
|
||||||
|
|
||||||
public PublicKey(String key) {
|
public PublicKey(final String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PublicKey() {}
|
public PublicKey() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initLocalTokenRemote(String ssoUri, String application) throws IOException, ParseException {
|
public static void initLocalTokenRemote(final String ssoUri, final String application) throws IOException, ParseException {
|
||||||
// check Token:
|
// check Token:
|
||||||
URL obj = new URL(ssoUri + "public_key");
|
final URL obj = new URL(ssoUri + "public_key");
|
||||||
//logger.debug("Request token from: {}", obj);
|
//LOGGER.debug("Request token from: {}", obj);
|
||||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
final HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||||
con.setRequestMethod("GET");
|
con.setRequestMethod("GET");
|
||||||
con.setRequestProperty("User-Agent", application);
|
con.setRequestProperty("User-Agent", application);
|
||||||
con.setRequestProperty("Cache-Control", "no-cache");
|
con.setRequestProperty("Cache-Control", "no-cache");
|
||||||
con.setRequestProperty("Content-Type", "application/json");
|
con.setRequestProperty("Content-Type", "application/json");
|
||||||
con.setRequestProperty("Accept", "application/json");
|
con.setRequestProperty("Accept", "application/json");
|
||||||
String ssoToken = ConfigBaseVariable.ssoToken();
|
final String ssoToken = ConfigBaseVariable.ssoToken();
|
||||||
if (ssoToken != null) {
|
if (ssoToken != null) {
|
||||||
con.setRequestProperty("Authorization", "Zota " + ssoToken);
|
con.setRequestProperty("Authorization", "Zota " + ssoToken);
|
||||||
}
|
}
|
||||||
int responseCode = con.getResponseCode();
|
final int responseCode = con.getResponseCode();
|
||||||
|
|
||||||
//logger.debug("GET Response Code :: {}", responseCode);
|
//LOGGER.debug("GET Response Code :: {}", responseCode);
|
||||||
if (responseCode == HttpURLConnection.HTTP_OK) { // success
|
if (responseCode == HttpURLConnection.HTTP_OK) { // success
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
final BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||||
|
|
||||||
String inputLine;
|
String inputLine;
|
||||||
StringBuffer response = new StringBuffer();
|
final StringBuffer response = new StringBuffer();
|
||||||
while ((inputLine = in.readLine()) != null) {
|
while ((inputLine = in.readLine()) != null) {
|
||||||
response.append(inputLine);
|
response.append(inputLine);
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
// print result
|
// print result
|
||||||
//logger.debug(response.toString());
|
//LOGGER.debug(response.toString());
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
final ObjectMapper mapper = new ObjectMapper();
|
||||||
PublicKey values = mapper.readValue(response.toString(), PublicKey.class);
|
final PublicKey values = mapper.readValue(response.toString(), PublicKey.class);
|
||||||
rsaPublicJWK = RSAKey.parse(values.key);
|
rsaPublicJWK = RSAKey.parse(values.key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.debug("GET JWT validator token not worked response code {} from {} ", responseCode, obj);
|
LOGGER.debug("GET JWT validator token not worked response code {} from {} ", responseCode, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initLocalToken(String baseUUID) throws Exception {
|
public static void initLocalToken(final String baseUUID) throws Exception {
|
||||||
// RSA signatures require a public and private RSA key pair, the public key
|
// RSA signatures require a public and private RSA key pair, the public key
|
||||||
// must be made known to the JWS recipient in order to verify the signatures
|
// must be made known to the JWS recipient in order to verify the signatures
|
||||||
try {
|
try {
|
||||||
String generatedStringForKey = baseUUID;
|
String generatedStringForKey = baseUUID;
|
||||||
if (generatedStringForKey == null) {
|
if (generatedStringForKey == null) {
|
||||||
logger.error(" Generate new UUID : {}", generatedStringForKey);
|
LOGGER.error(" Generate new UUID : {}", generatedStringForKey);
|
||||||
generatedStringForKey = UUID.randomUUID().toString();
|
generatedStringForKey = UUID.randomUUID().toString();
|
||||||
} else {
|
} else {
|
||||||
logger.error("USE UUID : {}", generatedStringForKey);
|
LOGGER.error("USE UUID : {}", generatedStringForKey);
|
||||||
}
|
}
|
||||||
rsaJWK = new RSAKeyGenerator(2048).keyID(generatedStringForKey).generate();
|
rsaJWK = new RSAKeyGenerator(2048).keyID(generatedStringForKey).generate();
|
||||||
rsaPublicJWK = rsaJWK.toPublicJWK();
|
rsaPublicJWK = rsaJWK.toPublicJWK();
|
||||||
logger.error("RSA key (all): " + rsaJWK.toJSONString());
|
LOGGER.error("RSA key (all): " + rsaJWK.toJSONString());
|
||||||
logger.error("RSA key (pub): " + rsaPublicJWK.toJSONString());
|
LOGGER.error("RSA key (pub): " + rsaPublicJWK.toJSONString());
|
||||||
} catch (JOSEException e) {
|
} catch (final JOSEException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
logger.debug("Can not generate teh public abnd private keys ...");
|
LOGGER.debug("Can not generate teh public abnd private keys ...");
|
||||||
rsaJWK = null;
|
rsaJWK = null;
|
||||||
rsaPublicJWK = null;
|
rsaPublicJWK = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initValidateToken(String publicKey) {
|
public static void initValidateToken(final String publicKey) {
|
||||||
try {
|
try {
|
||||||
rsaPublicJWK = RSAKey.parse(publicKey);
|
rsaPublicJWK = RSAKey.parse(publicKey);
|
||||||
} catch (ParseException e) {
|
} catch (final ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
logger.debug("Can not retrieve public Key !!!!!!!! RSAKey='{}'", publicKey);
|
LOGGER.debug("Can not retrieve public Key !!!!!!!! RSAKey='{}'", publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -136,81 +177,122 @@ public class JWTWrapper {
|
|||||||
* @param timeOutInMunites Expiration of the token.
|
* @param timeOutInMunites Expiration of the token.
|
||||||
* @return the encoded token
|
* @return the encoded token
|
||||||
*/
|
*/
|
||||||
public static String generateJWToken(long userID, String userLogin, String isuer, String application, Map<String, Object> rights, int timeOutInMunites) {
|
public static String generateJWToken(final long userID, final String userLogin, final String isuer, final String application, final Map<String, Object> rights, final int timeOutInMunites) {
|
||||||
if (rsaJWK == null) {
|
if (rsaJWK == null) {
|
||||||
logger.warn("JWT private key is not present !!!");
|
LOGGER.warn("JWT private key is not present !!!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
logger.debug(" ===> expire in : " + timeOutInMunites);
|
LOGGER.debug(" ===> expire in : " + timeOutInMunites);
|
||||||
logger.debug(" ===>" + new Date().getTime());
|
LOGGER.debug(" ===>" + new Date().getTime());
|
||||||
logger.debug(" ===>" + new Date(new Date().getTime()));
|
LOGGER.debug(" ===>" + new Date(new Date().getTime()));
|
||||||
logger.debug(" ===>" + new Date(new Date().getTime() - 60 * timeOutInMunites * 1000));
|
LOGGER.debug(" ===>" + new Date(new Date().getTime() - 60 * timeOutInMunites * 1000));
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
// Create RSA-signer with the private key
|
// Create RSA-signer with the private key
|
||||||
JWSSigner signer = new RSASSASigner(rsaJWK);
|
final JWSSigner signer = new RSASSASigner(rsaJWK);
|
||||||
|
|
||||||
logger.warn("timeOutInMunites= {}", timeOutInMunites);
|
LOGGER.warn("timeOutInMunites= {}", timeOutInMunites);
|
||||||
Date now = new Date();
|
final Date now = new Date();
|
||||||
logger.warn("now = {}", now);
|
LOGGER.warn("now = {}", now);
|
||||||
Date expiration = new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */);
|
final Date expiration = new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */);
|
||||||
|
|
||||||
logger.warn("expiration= {}", expiration);
|
LOGGER.warn("expiration= {}", expiration);
|
||||||
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)).claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now)
|
final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)).claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now)
|
||||||
.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning
|
.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning
|
||||||
// add right if needed:
|
// add right if needed:
|
||||||
if (rights != null && !rights.isEmpty()) {
|
if (rights != null && !rights.isEmpty()) {
|
||||||
builder.claim("right", rights);
|
builder.claim("right", rights);
|
||||||
}
|
}
|
||||||
// Prepare JWT with claims set
|
// Prepare JWT with claims set
|
||||||
JWTClaimsSet claimsSet = builder.build();
|
final JWTClaimsSet claimsSet = builder.build();
|
||||||
SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT)/*.keyID(rsaJWK.getKeyID())*/.build(), claimsSet);
|
final SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT)/*.keyID(rsaJWK.getKeyID())*/.build(), claimsSet);
|
||||||
|
|
||||||
// Compute the RSA signature
|
// Compute the RSA signature
|
||||||
signedJWT.sign(signer);
|
signedJWT.sign(signer);
|
||||||
// serialize the output...
|
// serialize the output...
|
||||||
return signedJWT.serialize();
|
return signedJWT.serialize();
|
||||||
} catch (JOSEException ex) {
|
} catch (final JOSEException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JWTClaimsSet validateToken(String signedToken, String isuer, String application) {
|
public static JWTClaimsSet validateToken(final String signedToken, final String isuer, final String application) {
|
||||||
if (rsaPublicJWK == null) {
|
|
||||||
logger.warn("JWT public key is not present !!!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
// On the consumer side, parse the JWS and verify its RSA signature
|
// On the consumer side, parse the JWS and verify its RSA signature
|
||||||
SignedJWT signedJWT = SignedJWT.parse(signedToken);
|
final SignedJWT signedJWT = SignedJWT.parse(signedToken);
|
||||||
|
|
||||||
JWSVerifier verifier = new RSASSAVerifier(rsaPublicJWK);
|
if (rsaPublicJWK == null) {
|
||||||
if (!signedJWT.verify(verifier)) {
|
LOGGER.warn("JWT public key is not present !!!");
|
||||||
logger.error("JWT token is NOT verified ");
|
if (!ConfigBaseVariable.getTestMode()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
final String rawSignature = signedJWT.getSigningInput().toString();
|
||||||
|
if (rawSignature.equals(TestSigner.test_signature)) {
|
||||||
|
// Test token : .application..
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final JWSVerifier verifier = new RSASSAVerifier(rsaPublicJWK);
|
||||||
|
if (!signedJWT.verify(verifier)) {
|
||||||
|
LOGGER.error("JWT token is NOT verified ");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) {
|
if (!new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) {
|
||||||
logger.error("JWT token is expired now = " + new Date() + " with=" + signedJWT.getJWTClaimsSet().getExpirationTime());
|
LOGGER.error("JWT token is expired now = " + new Date() + " with=" + signedJWT.getJWTClaimsSet().getExpirationTime());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isuer.equals(signedJWT.getJWTClaimsSet().getIssuer())) {
|
if (!isuer.equals(signedJWT.getJWTClaimsSet().getIssuer())) {
|
||||||
logger.error("JWT issuer is wong: '" + isuer + "' != '" + signedJWT.getJWTClaimsSet().getIssuer() + "'");
|
LOGGER.error("JWT issuer is wong: '" + isuer + "' != '" + signedJWT.getJWTClaimsSet().getIssuer() + "'");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (application != null) {
|
if (application != null) {
|
||||||
// TODO: verify the token is used for the correct application.
|
// TODO: verify the token is used for the correct application.
|
||||||
}
|
}
|
||||||
// the element must be validated outside ...
|
// the element must be validated outside ...
|
||||||
//logger.debug("JWT token is verified 'alice' =?= '" + signedJWT.getJWTClaimsSet().getSubject() + "'");
|
//LOGGER.debug("JWT token is verified 'alice' =?= '" + signedJWT.getJWTClaimsSet().getSubject() + "'");
|
||||||
//logger.debug("JWT token isuer 'https://c2id.com' =?= '" + signedJWT.getJWTClaimsSet().getIssuer() + "'");
|
//LOGGER.debug("JWT token isuer 'https://c2id.com' =?= '" + signedJWT.getJWTClaimsSet().getIssuer() + "'");
|
||||||
return signedJWT.getJWTClaimsSet();
|
return signedJWT.getJWTClaimsSet();
|
||||||
} catch (JOSEException ex) {
|
} catch (final JOSEException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
} catch (ParseException e) {
|
} catch (final ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String createJwtTestToken(final long userID, final String userLogin, final String isuer, final String application, final Map<String, Object> rights) {
|
||||||
|
if (!ConfigBaseVariable.getTestMode()) {
|
||||||
|
LOGGER.error("Test mode disable !!!!!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final int timeOutInMunites = 3600 * 24 * 31;
|
||||||
|
|
||||||
|
final Date now = new Date();
|
||||||
|
final Date expiration = new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */);
|
||||||
|
|
||||||
|
final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)).claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now)
|
||||||
|
.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning
|
||||||
|
// add right if needed:
|
||||||
|
if (rights != null && !rights.isEmpty()) {
|
||||||
|
builder.claim("right", rights);
|
||||||
|
}
|
||||||
|
// Prepare JWT with claims set
|
||||||
|
final JWTClaimsSet claimsSet = builder.build();
|
||||||
|
final SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT)/*.keyID(rsaJWK.getKeyID())*/.build(), claimsSet);
|
||||||
|
|
||||||
|
// Compute the RSA signature
|
||||||
|
signedJWT.sign(new TestSigner());
|
||||||
|
|
||||||
|
// serialize the output...
|
||||||
|
return signedJWT.serialize();
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
LOGGER.error("Can not generate Test Token...");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,4 +347,123 @@ public class TestTypes {
|
|||||||
|
|
||||||
DataAccess.delete(TypesTable.class, insertedData.id);
|
DataAccess.delete(TypesTable.class, insertedData.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Order(14)
|
||||||
|
@Test
|
||||||
|
public void testTextUpdateDirect() throws Exception {
|
||||||
|
|
||||||
|
final TypesTable test = new TypesTable();
|
||||||
|
test.textData = "test 1";
|
||||||
|
test.booleanData = null;
|
||||||
|
test.varcharData = "plop";
|
||||||
|
final TypesTable insertedData = DataAccess.insert(test);
|
||||||
|
Assertions.assertNotNull(insertedData);
|
||||||
|
Assertions.assertNotNull(insertedData.id);
|
||||||
|
Assertions.assertTrue(insertedData.id >= 0);
|
||||||
|
|
||||||
|
// Try to retrieve all the data:
|
||||||
|
final TypesTable retrieve = DataAccess.get(TypesTable.class, insertedData.id);
|
||||||
|
|
||||||
|
Assertions.assertNotNull(retrieve);
|
||||||
|
Assertions.assertNotNull(retrieve.id);
|
||||||
|
Assertions.assertEquals(insertedData.id, retrieve.id);
|
||||||
|
Assertions.assertNotNull(retrieve.textData);
|
||||||
|
Assertions.assertEquals(insertedData.textData, retrieve.textData);
|
||||||
|
Assertions.assertNull(retrieve.booleanData);
|
||||||
|
Assertions.assertNotNull(retrieve.varcharData);
|
||||||
|
Assertions.assertEquals(insertedData.varcharData, retrieve.varcharData);
|
||||||
|
|
||||||
|
// Update the text value:
|
||||||
|
retrieve.textData = "test 2";
|
||||||
|
retrieve.booleanData = true;
|
||||||
|
retrieve.varcharData = null;
|
||||||
|
final int nbUpdate = DataAccess.update(retrieve, insertedData.id);
|
||||||
|
Assertions.assertEquals(1, nbUpdate);
|
||||||
|
|
||||||
|
// Get new data
|
||||||
|
final TypesTable retrieve2 = DataAccess.get(TypesTable.class, insertedData.id);
|
||||||
|
|
||||||
|
Assertions.assertNotNull(retrieve2);
|
||||||
|
Assertions.assertNotNull(retrieve2.id);
|
||||||
|
Assertions.assertEquals(insertedData.id, retrieve2.id);
|
||||||
|
Assertions.assertNotNull(retrieve2.textData);
|
||||||
|
Assertions.assertEquals(retrieve.textData, retrieve2.textData);
|
||||||
|
Assertions.assertNotNull(retrieve2.booleanData);
|
||||||
|
Assertions.assertEquals(retrieve.booleanData, retrieve2.booleanData);
|
||||||
|
Assertions.assertNull(retrieve2.varcharData);
|
||||||
|
|
||||||
|
// test filter values:
|
||||||
|
retrieve.textData = "test 3";
|
||||||
|
retrieve.booleanData = false;
|
||||||
|
retrieve.varcharData = "test3";
|
||||||
|
final int nbUpdate2 = DataAccess.update(retrieve, insertedData.id, List.of("textData"));
|
||||||
|
Assertions.assertEquals(1, nbUpdate2);
|
||||||
|
|
||||||
|
// Get new data
|
||||||
|
final TypesTable retrieve3 = DataAccess.get(TypesTable.class, insertedData.id);
|
||||||
|
|
||||||
|
Assertions.assertNotNull(retrieve3);
|
||||||
|
Assertions.assertNotNull(retrieve3.id);
|
||||||
|
Assertions.assertEquals(insertedData.id, retrieve3.id);
|
||||||
|
Assertions.assertNotNull(retrieve3.textData);
|
||||||
|
Assertions.assertEquals(retrieve.textData, retrieve3.textData);
|
||||||
|
Assertions.assertNotNull(retrieve3.booleanData);
|
||||||
|
// note: retreive2
|
||||||
|
Assertions.assertEquals(retrieve2.booleanData, retrieve3.booleanData);
|
||||||
|
Assertions.assertNull(retrieve3.varcharData);
|
||||||
|
|
||||||
|
DataAccess.delete(TypesTable.class, insertedData.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(15)
|
||||||
|
@Test
|
||||||
|
public void testTextUpdateJson() throws Exception {
|
||||||
|
|
||||||
|
final TypesTable test = new TypesTable();
|
||||||
|
test.textData = "test 1";
|
||||||
|
test.booleanData = null;
|
||||||
|
test.varcharData = "plop";
|
||||||
|
final TypesTable insertedData = DataAccess.insert(test);
|
||||||
|
Assertions.assertNotNull(insertedData);
|
||||||
|
Assertions.assertNotNull(insertedData.id);
|
||||||
|
Assertions.assertTrue(insertedData.id >= 0);
|
||||||
|
|
||||||
|
// Try to retrieve all the data:
|
||||||
|
final TypesTable retrieve = DataAccess.get(TypesTable.class, insertedData.id);
|
||||||
|
|
||||||
|
Assertions.assertNotNull(retrieve);
|
||||||
|
Assertions.assertNotNull(retrieve.id);
|
||||||
|
Assertions.assertEquals(insertedData.id, retrieve.id);
|
||||||
|
Assertions.assertNotNull(retrieve.textData);
|
||||||
|
Assertions.assertEquals(insertedData.textData, retrieve.textData);
|
||||||
|
Assertions.assertNull(retrieve.booleanData);
|
||||||
|
Assertions.assertNotNull(retrieve.varcharData);
|
||||||
|
Assertions.assertEquals(insertedData.varcharData, retrieve.varcharData);
|
||||||
|
|
||||||
|
// Update the text value:
|
||||||
|
final String jsonData = """
|
||||||
|
{
|
||||||
|
"textData": "test 2",
|
||||||
|
"booleanData": true,
|
||||||
|
"varcharData": null
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final int nbUpdate = DataAccess.updateWithJson(TypesTable.class, insertedData.id, jsonData);
|
||||||
|
Assertions.assertEquals(1, nbUpdate);
|
||||||
|
|
||||||
|
// Get new data
|
||||||
|
final TypesTable retrieve2 = DataAccess.get(TypesTable.class, insertedData.id);
|
||||||
|
|
||||||
|
Assertions.assertNotNull(retrieve2);
|
||||||
|
Assertions.assertNotNull(retrieve2.id);
|
||||||
|
Assertions.assertEquals(insertedData.id, retrieve2.id);
|
||||||
|
Assertions.assertNotNull(retrieve2.textData);
|
||||||
|
Assertions.assertEquals(retrieve.textData, retrieve2.textData);
|
||||||
|
Assertions.assertNotNull(retrieve2.booleanData);
|
||||||
|
Assertions.assertEquals(retrieve.booleanData, retrieve2.booleanData);
|
||||||
|
Assertions.assertNull(retrieve2.varcharData);
|
||||||
|
|
||||||
|
DataAccess.delete(TypesTable.class, insertedData.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user