From 0260b4d4085ec856bcc23e0373844a66d8f871e7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 5 Jan 2025 20:08:56 +0100 Subject: [PATCH] [FEAT] update to new API of archidata --- back/pom.xml | 8 +- back/pom.xml.versionsBackup | 258 ++++++++++++++++++ .../org/kar/karusic/CodecBson/UUIDCodec.java | 27 ++ back/src/org/kar/karusic/WebLauncher.java | 28 +- .../src/org/kar/karusic/WebLauncherLocal.java | 3 +- .../org/kar/karusic/api/AlbumResource.java | 79 ++++-- .../org/kar/karusic/api/ArtistResource.java | 28 +- .../org/kar/karusic/api/GenderResource.java | 27 +- .../org/kar/karusic/api/PlaylistResource.java | 32 ++- .../org/kar/karusic/api/TrackResource.java | 52 ++-- .../kar/karusic/migration/Initialization.java | 68 ++--- .../karusic/migration/Migration20231126.java | 155 ----------- .../karusic/migration/Migration20240225.java | 12 - .../karusic/migration/Migration20240226.java | 118 -------- .../karusic/migration/Migration20250104.java | 144 ++++++++++ .../karusic/migration/Migration20250105.java | 31 +++ .../migration/model/CoverConversion.java | 3 + .../migration/model/MediaConversion.java | 6 +- ...UUIDConversion.java => OIDConversion.java} | 6 +- back/src/org/kar/karusic/model/Album.java | 6 +- back/src/org/kar/karusic/model/Artist.java | 6 +- back/src/org/kar/karusic/model/Gender.java | 13 +- back/src/org/kar/karusic/model/Playlist.java | 8 +- back/src/org/kar/karusic/model/Track.java | 8 +- back/src/resources/logback.xml | 18 ++ back/src/resources/simplelogger.properties | 9 +- .../src/test/kar/karusic/ConfigureDb.java | 126 +++++++++ back/test/src/test/kar/karusic/TestBase.java | 25 +- .../src/test/kar/karusic/TestMongoDb.java | 61 +++++ env_dev/docker-compose.yaml | 28 +- front/src/back-api/api/album-resource.ts | 48 ---- front/src/back-api/api/artist-resource.ts | 4 +- front/src/back-api/api/data-resource.ts | 14 +- front/src/back-api/api/gender-resource.ts | 4 +- front/src/back-api/api/playlist-resource.ts | 4 +- front/src/back-api/api/track-resource.ts | 4 +- front/src/back-api/model/album.ts | 6 +- front/src/back-api/model/artist.ts | 6 +- front/src/back-api/model/gender.ts | 6 +- front/src/back-api/model/index.ts | 1 + front/src/back-api/model/object-id.ts | 8 + front/src/back-api/model/playlist.ts | 11 +- front/src/back-api/model/track.ts | 10 +- front/src/back-api/model/user.ts | 10 +- front/src/back-api/rest-tools.ts | 13 +- front/src/components/Cover.tsx | 3 +- front/src/components/SearchInput.tsx | 2 - front/src/scene/home/HomePage.tsx | 2 +- front/src/scene/track/TrackRoutes.tsx | 1 - 49 files changed, 982 insertions(+), 568 deletions(-) create mode 100644 back/pom.xml.versionsBackup create mode 100644 back/src/org/kar/karusic/CodecBson/UUIDCodec.java create mode 100644 back/src/org/kar/karusic/migration/Migration20250104.java create mode 100644 back/src/org/kar/karusic/migration/Migration20250105.java rename back/src/org/kar/karusic/migration/model/{UUIDConversion.java => OIDConversion.java} (59%) create mode 100644 back/src/resources/logback.xml create mode 100644 back/test/src/test/kar/karusic/ConfigureDb.java create mode 100644 back/test/src/test/kar/karusic/TestMongoDb.java create mode 100644 front/src/back-api/model/object-id.ts diff --git a/back/pom.xml b/back/pom.xml index e1e15b9..c3625f2 100644 --- a/back/pom.xml +++ b/back/pom.xml @@ -20,12 +20,12 @@ kangaroo-and-rabbit archidata - 0.15.0 + 0.19.1-SNAPSHOT - org.slf4j - slf4j-simple - 2.1.0-alpha1 + ch.qos.logback + logback-classic + 1.4.11 com.fasterxml.jackson.datatype diff --git a/back/pom.xml.versionsBackup b/back/pom.xml.versionsBackup new file mode 100644 index 0000000..5bc7b55 --- /dev/null +++ b/back/pom.xml.versionsBackup @@ -0,0 +1,258 @@ + + + 4.0.0 + org.kar + karusic + 0.1.0 + + 3.1 + 21 + 21 + 3.1.1 + + + + gitea + https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven + + + + + kangaroo-and-rabbit + archidata + 0.14.3-SNAPSHOT + + + org.slf4j + slf4j-simple + 2.1.0-alpha1 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.18.0-rc1 + + + + org.junit.jupiter + junit-jupiter-api + 5.11.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.11.0 + test + + + net.revelc.code.formatter + formatter-maven-plugin + 2.24.1 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.5.0 + + + + src + test/src + ${project.basedir}/out/maven/ + + + src/resources + + + + + ${basedir}/test/resources + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + org.kar.karusic.WebLauncher + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + maven-assembly-plugin + + + + fully.qualified.MainClass + + + + jar-with-dependencies + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + private + true + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + exec-application + package + + java + + + + + org.kar.karusic.WebLauncher + + + + + net.revelc.code.formatter + formatter-maven-plugin + 2.23.0 + + UTF-8 + LF + Formatter.xml + + src/ + test/src + + + **/*.java + + + module-info.java + + + + + + validate + + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.8.5.0 + + spotbugs-security-include.xml + spotbugs-security-exclude.xml + + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + public + + + + + diff --git a/back/src/org/kar/karusic/CodecBson/UUIDCodec.java b/back/src/org/kar/karusic/CodecBson/UUIDCodec.java new file mode 100644 index 0000000..43fb5fb --- /dev/null +++ b/back/src/org/kar/karusic/CodecBson/UUIDCodec.java @@ -0,0 +1,27 @@ +package org.kar.karusic.CodecBson; + +import java.util.UUID; + +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +public class UUIDCodec implements Codec { + + @Override + public UUID decode(final BsonReader reader, final DecoderContext decoderContext) { + return UUID.fromString(reader.readString()); + } + + @Override + public void encode(final BsonWriter writer, final UUID value, final EncoderContext encoderContext) { + writer.writeString(value.toString()); + } + + @Override + public Class getEncoderClass() { + return UUID.class; + } +} \ No newline at end of file diff --git a/back/src/org/kar/karusic/WebLauncher.java b/back/src/org/kar/karusic/WebLauncher.java index 25f33f8..71ad576 100755 --- a/back/src/org/kar/karusic/WebLauncher.java +++ b/back/src/org/kar/karusic/WebLauncher.java @@ -12,15 +12,17 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.server.ResourceConfig; -import org.kar.archidata.GlobalConfiguration; import org.kar.archidata.UpdateJwtPublicKey; import org.kar.archidata.api.DataResource; import org.kar.archidata.api.ProxyResource; import org.kar.archidata.catcher.GenericCatcher; +import org.kar.archidata.db.DbConfig; +import org.kar.archidata.exception.DataAccessException; import org.kar.archidata.filter.CORSFilter; import org.kar.archidata.filter.OptionFilter; import org.kar.archidata.migration.MigrationEngine; import org.kar.archidata.tools.ConfigBaseVariable; +import org.kar.archidata.tools.ContextGenericTools; import org.kar.karusic.api.AlbumResource; import org.kar.karusic.api.ArtistResource; import org.kar.karusic.api.Front; @@ -35,6 +37,8 @@ import org.kar.karusic.migration.Migration20231126; import org.kar.karusic.migration.Migration20240225; import org.kar.karusic.migration.Migration20240226; import org.kar.karusic.migration.Migration20240907; +import org.kar.karusic.migration.Migration20250104; +import org.kar.karusic.migration.Migration20250105; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,8 +67,10 @@ public class WebLauncher { migrationEngine.add(new Migration20240225()); migrationEngine.add(new Migration20240226()); migrationEngine.add(new Migration20240907()); + migrationEngine.add(new Migration20250104()); + migrationEngine.add(new Migration20250105()); WebLauncher.LOGGER.info("Migrate the DB [START]"); - migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); + migrationEngine.migrateWaitAdmin(new DbConfig()); WebLauncher.LOGGER.info("Migrate the DB [STOP]"); } @@ -83,26 +89,26 @@ public class WebLauncher { public void plop(final String aaa) { // List available Image Readers - System.out.println("Available Image Readers:"); + WebLauncher.LOGGER.trace("Available Image Readers:"); final Iterator readers = ImageIO.getImageReadersByFormatName(aaa); while (readers.hasNext()) { final ImageReader reader = readers.next(); - System.out.println("Reader: " + reader.getOriginatingProvider().getDescription(null)); - System.out.println("Reader CN: " + reader.getOriginatingProvider().getPluginClassName()); + WebLauncher.LOGGER.trace("Reader: " + reader.getOriginatingProvider().getDescription(null)); + WebLauncher.LOGGER.trace("Reader CN: " + reader.getOriginatingProvider().getPluginClassName()); // ImageIO.deregisterServiceProvider(reader.getOriginatingProvider()); } // List available Image Writers - System.out.println("\nAvailable Image Writers:"); + WebLauncher.LOGGER.trace("\nAvailable Image Writers:"); final Iterator writers = ImageIO.getImageWritersByFormatName(aaa); while (writers.hasNext()) { final ImageWriter writer = writers.next(); - System.out.println("Writer: " + writer.getOriginatingProvider().getDescription(null)); - System.out.println("Writer CN: " + writer.getOriginatingProvider().getPluginClassName()); + WebLauncher.LOGGER.trace("Writer: " + writer.getOriginatingProvider().getDescription(null)); + WebLauncher.LOGGER.trace("Writer CN: " + writer.getOriginatingProvider().getPluginClassName()); } } - public void process() throws InterruptedException { + public void process() throws InterruptedException, DataAccessException { ImageIO.scanForPlugins(); plop("jpeg"); @@ -137,6 +143,8 @@ public class WebLauncher { rc.register(HealthCheck.class); rc.register(Front.class); + ContextGenericTools.addJsr310(rc); + // add jackson to be discover when we are ins standalone server rc.register(JacksonFeature.class); // enable this to show low level request @@ -148,7 +156,7 @@ public class WebLauncher { // System.out.println(" getDBLogin: '" + ConfigVariable.getDBLogin() + "'"); // System.out.println(" getDBPassword: '" + ConfigVariable.getDBPassword() + "'"); // System.out.println(" getDBName: '" + ConfigVariable.getDBName() + "'"); - System.out.println(" ==> " + GlobalConfiguration.dbConfig); + System.out.println(" ==> " + new DbConfig()); System.out.println("OAuth service " + getBaseURI()); this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); final HttpServer serverLink = this.server; diff --git a/back/src/org/kar/karusic/WebLauncherLocal.java b/back/src/org/kar/karusic/WebLauncherLocal.java index f6ddc5d..7582acb 100755 --- a/back/src/org/kar/karusic/WebLauncherLocal.java +++ b/back/src/org/kar/karusic/WebLauncherLocal.java @@ -4,6 +4,7 @@ import java.util.List; import org.kar.archidata.api.DataResource; import org.kar.archidata.api.ProxyResource; +import org.kar.archidata.exception.DataAccessException; import org.kar.archidata.externalRestApi.AnalyzeApi; import org.kar.archidata.externalRestApi.TsGenerateApi; import org.kar.archidata.tools.ConfigBaseVariable; @@ -43,7 +44,7 @@ public class WebLauncherLocal extends WebLauncher { } @Override - public void process() throws InterruptedException { + public void process() throws InterruptedException, DataAccessException { if (true) { // for local test: ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; diff --git a/back/src/org/kar/karusic/api/AlbumResource.java b/back/src/org/kar/karusic/api/AlbumResource.java index 237dfa3..db3c251 100644 --- a/back/src/org/kar/karusic/api/AlbumResource.java +++ b/back/src/org/kar/karusic/api/AlbumResource.java @@ -9,9 +9,9 @@ import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.TypeScriptProgress; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.AddOnDataJson; -import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; +import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.tools.DataTools; import org.kar.karusic.model.Album; @@ -41,8 +41,9 @@ public class AlbumResource { @Path("{id}") @RolesAllowed("USER") @Operation(description = "Get a specific Album with his ID") - public static Album get(@PathParam("id") final Long id) throws Exception { + public Album get(@PathParam("id") final Long id) throws Exception { return DataAccess.get(Album.class, id); + // return this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).first(); } @GET @@ -50,6 +51,8 @@ public class AlbumResource { @Operation(description = "Get all the available Albums") public List gets() throws Exception { return DataAccess.gets(Album.class); + // final Query query = this.morphiaService.getDatastore().find(Album.class); + // return query.stream().toList(); } @POST @@ -57,6 +60,12 @@ public class AlbumResource { @Consumes(MediaType.APPLICATION_JSON) @Operation(description = "Add an album (when all the data already exist)") public Album post(final Album data) throws Exception { + // TODO: how to manage the checker ??? + // final Album ret = this.morphiaService.getDatastore().save(data); + // return ret; + /* final MongoCollection trackCollection = db.getCollection("TTRACLK", Track.class); final InsertOneResult res = trackCollection.insertOne(plop); LOGGER.warn("plpop {}", res); final + * ObjectId ploppppp = res.getInsertedId().asObjectId().getValue(); LOGGER.warn("plpop 2522 {}", res.getInsertedId().asObjectId().getValue()); final Track ret = + * trackCollection.find(Filters.eq("_id", res.getInsertedId().asObjectId().getValue())) .first(); System.out.println("Grade found:\t" + ret); */ return DataAccess.insert(data, new CheckFunction(CHECKER)); } @@ -66,37 +75,45 @@ public class AlbumResource { @Consumes(MediaType.APPLICATION_JSON) @Operation(description = "Update a specific album") public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest) throws Exception { + // final Query query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); + // final UpdateOperations ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class) + // .set("name", master.getName()); + // this.morphiaService.getDatastore().update(query, ops); + // return Response.ok(master).build(); + DataAccess.updateWithJson(Album.class, id, jsonRequest, new CheckFunction(CHECKER)); return DataAccess.get(Album.class, id); } + // @PUT + // @Path("{id}") + // @RolesAllowed("ADMIN") + // @Consumes(MediaType.APPLICATION_JSON) + // @Operation(description = "Update a specific album") + // public Album put(@PathParam("id") final Long id, final Album album) + // throws Exception { + // final Query query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); + // final UpdateOperations ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class) + // .set("name", album.getName()); + // this.morphiaService.getDatastore().update(query, ops); + // return Response.ok(album).build(); + // } + @DELETE @Path("{id}") @RolesAllowed("ADMIN") @Operation(description = "Remove a specific album") public void remove(@PathParam("id") final Long id) throws Exception { DataAccess.delete(Album.class, id); + // this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).delete(); } - @POST - @Path("{id}/track/{trackId}") - @RolesAllowed("ADMIN") - @Consumes({ MediaType.MULTIPART_FORM_DATA }) - @Operation(description = "Add a Track on a specific album") - public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { - AddOnManyToMany.removeLink(Album.class, id, "track", trackId); - return DataAccess.get(Album.class, id); - } - - @DELETE - @Path("{id}/track/{trackId}") - @RolesAllowed("ADMIN") - @Operation(description = "Remove a Track on a specific album") - public Album removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { - AddOnManyToMany.removeLink(Album.class, id, "track", trackId); - return DataAccess.get(Album.class, id); - } - + /* @POST + * @Path("{id}/track/{trackId}") + * @RolesAllowed("ADMIN") + * @Consumes({ MediaType.MULTIPART_FORM_DATA }) + * @Operation(description = "Add a Track on a specific album") public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { + * AddOnManyToMany.removeLink(this.dam, Album.class, id, "track", trackId); return this.dam.get(Album.class, id); } */ @POST @Path("{id}/cover") @RolesAllowed("ADMIN") @@ -105,12 +122,14 @@ public class AlbumResource { @TypeScriptProgress public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { - if (uri != null) { - DataTools.uploadCoverFromUri(Album.class, id, uri); - } else { - DataTools.uploadCover(Album.class, id, fileInputStream, fileMetaData); + try (DBAccess db = DBAccess.createInterface()) { + if (uri != null) { + DataTools.uploadCoverFromUri(db, Album.class, id, uri); + } else { + DataTools.uploadCover(db, Album.class, id, fileInputStream, fileMetaData); + } + return db.get(Album.class, id); } - return DataAccess.get(Album.class, id); } @DELETE @@ -118,7 +137,9 @@ public class AlbumResource { @RolesAllowed("ADMIN") @Operation(description = "Remove a cover on a specific album") public Album removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { - AddOnDataJson.removeLink(Album.class, id, "covers", coverId); - return DataAccess.get(Album.class, id); + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Album.class, "id", id, "covers", coverId); + return db.get(Album.class, id); + } } } diff --git a/back/src/org/kar/karusic/api/ArtistResource.java b/back/src/org/kar/karusic/api/ArtistResource.java index 2507576..908207e 100644 --- a/back/src/org/kar/karusic/api/ArtistResource.java +++ b/back/src/org/kar/karusic/api/ArtistResource.java @@ -2,15 +2,16 @@ package org.kar.karusic.api; import java.io.InputStream; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.TypeScriptProgress; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.AddOnDataJson; +import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.tools.DataTools; import org.kar.karusic.model.Artist; @@ -38,7 +39,7 @@ public class ArtistResource { @GET @Path("{id}") @RolesAllowed("USER") - public static Artist get(@PathParam("id") final Long id) throws Exception { + public Artist get(@PathParam("id") final Long id) throws Exception { return DataAccess.get(Artist.class, id); } @@ -78,20 +79,23 @@ public class ArtistResource { @TypeScriptProgress public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { - if (uri != null) { - DataTools.uploadCoverFromUri(Artist.class, id, uri); - } else { - DataTools.uploadCover(Artist.class, id, fileInputStream, fileMetaData); + try (DBAccess db = DBAccess.createInterface()) { + if (uri != null) { + DataTools.uploadCoverFromUri(db, Artist.class, id, uri); + } else { + DataTools.uploadCover(db, Artist.class, id, fileInputStream, fileMetaData); + } + return db.get(Artist.class, id); } - return DataAccess.get(Artist.class, id); } @DELETE @Path("{id}/cover/{coverId}") @RolesAllowed("ADMIN") - public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { - LOGGER.error("klmlmkmlkmlklmklmk"); - AddOnDataJson.removeLink(Artist.class, id, "covers", coverId); - return DataAccess.get(Artist.class, id); + public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception { + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Artist.class, "id", id, "covers", coverId); + return db.get(Artist.class, id); + } } } diff --git a/back/src/org/kar/karusic/api/GenderResource.java b/back/src/org/kar/karusic/api/GenderResource.java index 00272ed..ea3cd4a 100644 --- a/back/src/org/kar/karusic/api/GenderResource.java +++ b/back/src/org/kar/karusic/api/GenderResource.java @@ -2,15 +2,16 @@ package org.kar.karusic.api; import java.io.InputStream; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.TypeScriptProgress; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.AddOnDataJson; +import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.tools.DataTools; import org.kar.karusic.model.Gender; @@ -38,7 +39,7 @@ public class GenderResource { @GET @Path("{id}") @RolesAllowed("USER") - public static Gender get(@PathParam("id") final Long id) throws Exception { + public Gender get(@PathParam("id") final Long id) throws Exception { return DataAccess.get(Gender.class, id); } @@ -78,19 +79,23 @@ public class GenderResource { @TypeScriptProgress public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { - if (uri != null) { - DataTools.uploadCoverFromUri(Gender.class, id, uri); - } else { - DataTools.uploadCover(Gender.class, id, fileInputStream, fileMetaData); + try (DBAccess db = DBAccess.createInterface()) { + if (uri != null) { + DataTools.uploadCoverFromUri(db, Gender.class, id, uri); + } else { + DataTools.uploadCover(db, Gender.class, id, fileInputStream, fileMetaData); + } + return db.get(Gender.class, id); } - return DataAccess.get(Gender.class, id); } @DELETE @Path("{id}/cover/{coverId}") @RolesAllowed("ADMIN") - public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { - AddOnDataJson.removeLink(Gender.class, id, "covers", coverId); - return DataAccess.get(Gender.class, id); + public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception { + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Gender.class, "id", id, "covers", coverId); + return db.get(Gender.class, id); + } } } diff --git a/back/src/org/kar/karusic/api/PlaylistResource.java b/back/src/org/kar/karusic/api/PlaylistResource.java index 24c0238..e8e0729 100644 --- a/back/src/org/kar/karusic/api/PlaylistResource.java +++ b/back/src/org/kar/karusic/api/PlaylistResource.java @@ -2,14 +2,14 @@ package org.kar.karusic.api; import java.io.InputStream; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.AsyncType; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.AddOnDataJson; -import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; +import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.tools.DataTools; import org.kar.karusic.model.Playlist; @@ -37,7 +37,7 @@ public class PlaylistResource { @GET @Path("{id}") @RolesAllowed("USER") - public static Playlist get(@PathParam("id") final Long id) throws Exception { + public Playlist get(@PathParam("id") final Long id) throws Exception { return DataAccess.get(Playlist.class, id); } @@ -75,16 +75,20 @@ public class PlaylistResource { @RolesAllowed("ADMIN") @Consumes({ MediaType.MULTIPART_FORM_DATA }) public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { - AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId); - return DataAccess.get(Playlist.class, id); + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId); + return db.get(Playlist.class, id); + } } @DELETE @Path("{id}/track/{trackId}") @RolesAllowed("ADMIN") public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { - AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId); - return DataAccess.get(Playlist.class, id); + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId); + return db.get(Playlist.class, id); + } } @POST @@ -94,14 +98,18 @@ public class PlaylistResource { @AsyncType(Playlist.class) public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { - DataTools.uploadCover(Playlist.class, id, fileInputStream, fileMetaData); + try (DBAccess db = DBAccess.createInterface()) { + DataTools.uploadCover(db, Playlist.class, id, fileInputStream, fileMetaData); + } } @DELETE @Path("{id}/cover/{coverId}") @RolesAllowed("ADMIN") - public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { - AddOnDataJson.removeLink(Playlist.class, id, "covers", coverId); - return DataAccess.get(Playlist.class, id); + public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception { + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Playlist.class, "id", id, "covers", coverId); + return DataAccess.get(Playlist.class, id); + } } } diff --git a/back/src/org/kar/karusic/api/TrackResource.java b/back/src/org/kar/karusic/api/TrackResource.java index 0dec8aa..6f9a4b8 100644 --- a/back/src/org/kar/karusic/api/TrackResource.java +++ b/back/src/org/kar/karusic/api/TrackResource.java @@ -5,16 +5,16 @@ import java.io.InputStream; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.TypeScriptProgress; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.AddOnDataJson; -import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; +import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson; import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.model.Data; import org.kar.archidata.tools.DataTools; @@ -44,7 +44,7 @@ public class TrackResource { @GET @Path("{id}") @RolesAllowed("USER") - public static Track get(@PathParam("id") final Long id) throws Exception { + public Track get(@PathParam("id") final Long id) throws Exception { return DataAccess.get(Track.class, id); } @@ -82,16 +82,20 @@ public class TrackResource { @RolesAllowed("ADMIN") @Consumes({ MediaType.MULTIPART_FORM_DATA }) public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { - AddOnManyToMany.removeLink(Track.class, id, "artist", artistId); - return DataAccess.get(Track.class, id); + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId); + return DataAccess.get(Track.class, id); + } } @DELETE @Path("{id}/artist/{trackId}") @RolesAllowed("ADMIN") public Track removeTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { - AddOnManyToMany.removeLink(Track.class, id, "artist", artistId); - return DataAccess.get(Track.class, id); + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId); + return DataAccess.get(Track.class, id); + } } @POST @@ -101,20 +105,24 @@ public class TrackResource { @TypeScriptProgress public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { - if (uri != null) { - DataTools.uploadCoverFromUri(Track.class, id, uri); - } else { - DataTools.uploadCover(Track.class, id, fileInputStream, fileMetaData); + try (DBAccess db = DBAccess.createInterface()) { + if (uri != null) { + DataTools.uploadCoverFromUri(db, Track.class, id, uri); + } else { + DataTools.uploadCover(db, Track.class, id, fileInputStream, fileMetaData); + } + return DataAccess.get(Track.class, id); } - return DataAccess.get(Track.class, id); } @DELETE @Path("{id}/cover/{coverId}") @RolesAllowed("ADMIN") - public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { - AddOnDataJson.removeLink(Track.class, id, "covers", coverId); - return DataAccess.get(Track.class, id); + public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception { + try (DBAccess db = DBAccess.createInterface()) { + AddOnDataJson.removeLink(db, Track.class, "id", id, "covers", coverId); + return db.get(Track.class, id); + } } @POST @@ -132,7 +140,7 @@ public class TrackResource { @FormDataParam("file") final InputStream fileInputStream, // @FormDataParam("file") final FormDataContentDisposition fileMetaData // ) { - try { + try (DBAccess db = DBAccess.createInterface()) { // correct input string stream : trackId = DataTools.multipartCorrection(trackId); albumId = DataTools.multipartCorrection(albumId); @@ -153,12 +161,12 @@ public class TrackResource { final long tmpUID = DataTools.getTmpDataId(); final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID); - Data data = DataTools.getWithSha512(sha512); + Data data = DataTools.getWithSha512(db, sha512); if (data == null) { LOGGER.info("Need to add the data in the BDD ... "); try { - data = DataTools.createNewData(tmpUID, fileMetaData.getFileName(), sha512); + data = DataTools.createNewData(db, tmpUID, fileMetaData.getFileName(), sha512); } catch (final IOException ex) { DataTools.removeTemporaryFile(tmpUID); ex.printStackTrace(); @@ -170,7 +178,7 @@ public class TrackResource { } } else if (data.deleted) { LOGGER.info("Data already exist but deleted"); - DataTools.undelete(data.uuid); + DataTools.undelete(db, data.oid); data.deleted = false; } else { LOGGER.info("Data already exist ... all good"); @@ -182,14 +190,14 @@ public class TrackResource { trackElem.track = trackId != null ? Long.parseLong(trackId) : null; trackElem.albumId = albumId != null ? Long.parseLong(albumId) : null; trackElem.genderId = genderId != null ? Long.parseLong(genderId) : null; - trackElem.dataId = data.uuid; + trackElem.dataId = data.oid; // Now list of artist has an internal management: if (artistId != null) { trackElem.artists = new ArrayList<>(); trackElem.artists.add(artistId != null ? Long.parseLong(artistId) : null); } trackElem = DataAccess.insert(trackElem, new CheckFunction(CHECKER)); - /* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { DataAccess.addLink(Track.class, trackElem.id, "artist", artistElem.id); } */ + /* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { this.dam.addLink(Track.class, trackElem.id, "artist", artistElem.id); } */ return Response.ok(trackElem).build(); } catch (final Exception ex) { LOGGER.info("Catch an unexpected error ... {}", ex.getMessage()); diff --git a/back/src/org/kar/karusic/migration/Initialization.java b/back/src/org/kar/karusic/migration/Initialization.java index 0396ff2..9b497ea 100644 --- a/back/src/org/kar/karusic/migration/Initialization.java +++ b/back/src/org/kar/karusic/migration/Initialization.java @@ -2,7 +2,7 @@ package org.kar.karusic.migration; import java.util.List; -import org.kar.archidata.dataAccess.DataAccess; +import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.migration.MigrationSqlStep; import org.kar.archidata.model.Data; import org.kar.archidata.model.User; @@ -35,35 +35,35 @@ public class Initialization extends MigrationSqlStep { addClass(elem); } - addAction(""" - INSERT INTO `gender` (`id`, `name`, `description`) VALUES - (1, 'Variété française', NULL), - (2, 'Pop', NULL), - (3, 'inconnue', NULL), - (4, 'Disco', NULL), - (5, 'Enfants', NULL), - (6, 'Portugaise', NULL), - (7, 'Apprentissage', NULL), - (8, 'Blues', NULL), - (9, 'Jazz', NULL), - (10, 'Chanson Noël', NULL), - (11, 'DubStep', NULL), - (12, 'Rap français', NULL), - (13, 'Classique', NULL), - (14, 'Rock', NULL), - (15, 'Electro', NULL), - (16, 'Celtique', NULL), - (17, 'Country', NULL), - (18, 'Variété Québéquoise', NULL), - (19, 'Médiéval', NULL), - (20, 'Variété Italienne', NULL), - (21, 'Comédie Musicale', NULL), - (22, 'Vianney', NULL), - (23, 'Bande Original', NULL), - (24, 'Bande Originale', NULL), - (25, 'Variété Belge', NULL), - (26, 'Gospel', NULL); - """); + addAction((final DBAccess da) -> { + final List data = List.of(// + new Gender(1L, "Variété française"), // + new Gender(2L, "Pop"), // + new Gender(3L, "inconnue"), // + new Gender(4L, "Disco"), // + new Gender(5L, "Enfants"), // + new Gender(6L, "Portugaise"), // + new Gender(7L, "Apprentissage"), // + new Gender(8L, "Blues"), // + new Gender(9L, "Jazz"), // + new Gender(10L, "Chanson Noël"), // + new Gender(11L, "DubStep"), // + new Gender(12L, "Rap français"), // + new Gender(13L, "Classique"), // + new Gender(14L, "Rock"), // + new Gender(15L, "Electro"), // + new Gender(16L, "Celtique"), // + new Gender(17L, "Country"), // + new Gender(18L, "Variété Québéquoise"), // + new Gender(19L, "Médiéval"), // + new Gender(20L, "Variété Italienne"), // + new Gender(21L, "Comédie Musicale"), // + new Gender(22L, "Vianney"), // + new Gender(23L, "Bande Original"), // + new Gender(24L, "Bande Originale"), // + new Gender(25L, "Variété Belge"), // + new Gender(26L, "Gospel")); + }); // set start increment element to permit to add after default elements addAction(""" ALTER TABLE `album` AUTO_INCREMENT = 1000; @@ -85,10 +85,10 @@ public class Initialization extends MigrationSqlStep { """, "mysql"); } - public static void dropAll() { + public static void dropAll(final DBAccess da) { for (final Class element : CLASSES_BASE) { try { - DataAccess.drop(element); + da.drop(element); } catch (final Exception ex) { LOGGER.error("Fail to drop table !!!!!!"); ex.printStackTrace(); @@ -96,10 +96,10 @@ public class Initialization extends MigrationSqlStep { } } - public static void cleanAll() { + public static void cleanAll(final DBAccess da) { for (final Class element : CLASSES_BASE) { try { - DataAccess.cleanAll(element); + da.cleanAll(element); } catch (final Exception ex) { LOGGER.error("Fail to clean table !!!!!!"); ex.printStackTrace(); diff --git a/back/src/org/kar/karusic/migration/Migration20231126.java b/back/src/org/kar/karusic/migration/Migration20231126.java index de12648..2ceaf06 100644 --- a/back/src/org/kar/karusic/migration/Migration20231126.java +++ b/back/src/org/kar/karusic/migration/Migration20231126.java @@ -11,159 +11,4 @@ public class Migration20231126 extends MigrationSqlStep { return "migration-2023-11-26: reorder the migration for the new API of archidata"; } - public Migration20231126() { - - } - - @Override - public void generateStep() throws Exception { - // update migration update (last one) - addAction(""" - ALTER TABLE `KAR_migration` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - ADD `version` int NOT NULL DEFAULT '2' AFTER `deleted`, - CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'Name of the migration' AFTER `version`, - CHANGE `terminated` `terminated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'if the migration is well terminated or not' AFTER `name`, - CHANGE `stepId` `stepId` int NULL COMMENT 'index in the migration progression' AFTER `terminated`, - CHANGE `count` `count` int NULL COMMENT 'number of element in the migration' AFTER `stepId`, - CHANGE `log` `log` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Log generate by the migration' AFTER `count`; - """); - - addAction(""" - ALTER TABLE `album` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, - CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`, - CHANGE `publication` `publication` date NULL AFTER `description`; - """); - addAction(""" - ALTER TABLE `album_link_cover` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `album_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `artist` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - CHANGE `firstName` `firstName` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `description`, - CHANGE `surname` `surname` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `firstName`, - CHANGE `birth` `birth` date NULL AFTER `surname`, - CHANGE `death` `death` date NULL AFTER `birth`; - """); - addAction(""" - ALTER TABLE `artist_link_cover` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `artist_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `data` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - CHANGE `sha512` `sha512` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Sha512 of the data' AFTER `deleted`, - CHANGE `mimeType` `mimeType` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Mime -type of the media' AFTER `sha512`, - CHANGE `size` `size` bigint NOT NULL COMMENT 'Size in Byte of the data' AFTER `mimeType`; - """); - addAction(""" - ALTER TABLE `gender` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, - CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`; - """); - addAction(""" - ALTER TABLE `gender_link_cover` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `gender_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `playlist` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, - CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`; - """); - addAction(""" - ALTER TABLE `playlist_link_cover` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `playlist_link_track` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `track_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `track` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, - CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`, - CHANGE `genderId` `genderId` bigint NULL AFTER `description`, - CHANGE `albumId` `albumId` bigint NULL AFTER `genderId`, - CHANGE `track` `track` bigint NULL AFTER `albumId`, - CHANGE `dataId` `dataId` bigint NULL AFTER `track`, - CHANGE `artists` `artists` text COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `dataId`; - """); - addAction(""" - ALTER TABLE `track_link_cover` - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, - CHANGE `track_id` `object1id` bigint NOT NULL AFTER `deleted`, - CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; - """); - addAction(""" - ALTER TABLE `user` - CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, - CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, - CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, - CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, - CHANGE `login` `login` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, - CHANGE `lastConnection` `lastConnection` timestamp(3) NULL AFTER `login`, - CHANGE `admin` `admin` tinyint(1) NOT NULL DEFAULT '0' AFTER `lastConnection`, - CHANGE `blocked` `blocked` tinyint(1) NOT NULL DEFAULT '0' AFTER `admin`, - CHANGE `removed` `removed` tinyint(1) NOT NULL DEFAULT '0' AFTER `blocked`; - """); - addAction(""" - CREATE TABLE `user_link_cover` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key of the base' , - `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' , - `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'When update the object' , - `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' , - `object1Id` bigint NOT NULL COMMENT 'Object reference 1' , - `object2Id` bigint NOT NULL COMMENT 'Object reference 2' , - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; - """); - } - } diff --git a/back/src/org/kar/karusic/migration/Migration20240225.java b/back/src/org/kar/karusic/migration/Migration20240225.java index 0714681..399f07f 100644 --- a/back/src/org/kar/karusic/migration/Migration20240225.java +++ b/back/src/org/kar/karusic/migration/Migration20240225.java @@ -11,16 +11,4 @@ public class Migration20240225 extends MigrationSqlStep { return "migration-2024-02-25: change model of thrack to use real json"; } - public Migration20240225() { - - } - - @Override - public void generateStep() throws Exception { - // update migration update (last one) - addAction(""" - UPDATE `track` SET artists = CONCAT('[', artists, ']') WHERE artists IS NOT NULL - """); - } - } diff --git a/back/src/org/kar/karusic/migration/Migration20240226.java b/back/src/org/kar/karusic/migration/Migration20240226.java index 8e189c0..2f06735 100644 --- a/back/src/org/kar/karusic/migration/Migration20240226.java +++ b/back/src/org/kar/karusic/migration/Migration20240226.java @@ -1,22 +1,6 @@ package org.kar.karusic.migration; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.kar.archidata.api.DataResource; -import org.kar.archidata.dataAccess.DataAccess; -import org.kar.archidata.dataAccess.addOn.model.LinkTableLongLong; -import org.kar.archidata.dataAccess.options.AccessDeletedItems; -import org.kar.archidata.dataAccess.options.OverrideTableName; import org.kar.archidata.migration.MigrationSqlStep; -import org.kar.archidata.tools.UuidUtils; -import org.kar.karusic.migration.model.CoverConversion; -import org.kar.karusic.migration.model.MediaConversion; -import org.kar.karusic.migration.model.UUIDConversion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,106 +14,4 @@ public class Migration20240226 extends MigrationSqlStep { return "migration-2024-02-26: convert base with UUID"; } - public Migration20240226() { - - } - - @Override - public void generateStep() throws Exception { - addAction(""" - ALTER TABLE `data` ADD `uuid` binary(16) AFTER `id`; - """); - addAction(() -> { - final List datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); - for (final UUIDConversion elem : datas) { - elem.uuid = UuidUtils.nextUUID(); - } - for (final UUIDConversion elem : datas) { - DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("data")); - } - }); - addAction(""" - ALTER TABLE `data` CHANGE `uuid` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); - """); - final List tableToTransform = List.of("album", "artist", "gender", "playlist", "track", "user"); - for (final String tableName : tableToTransform) { - addAction("ALTER TABLE `" + tableName + "` ADD `covers` text NULL;"); - addAction(() -> { - final List datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); - final List medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName)); - final List links = DataAccess.gets(LinkTableLongLong.class, new OverrideTableName(tableName + "_link_cover")); - LOGGER.info("Get somes data: {} {} {}", datas.size(), medias.size(), links.size()); - for (final CoverConversion media : medias) { - final List values = new ArrayList<>(); - for (final LinkTableLongLong link : links) { - if (link.object1Id.equals(media.id)) { - for (final UUIDConversion data : datas) { - if (data.id.equals(link.object2Id)) { - values.add(data.uuid); - break; - } - } - break; - } - } - if (values.size() != 0) { - media.covers = values; - LOGGER.info(" update: {} => {}", media.id, media.covers); - DataAccess.update(media, media.id, List.of("covers"), new OverrideTableName(tableName)); - } - } - }); - addAction("DROP TABLE `" + tableName + "_link_cover`;"); - } - addAction(""" - ALTER TABLE `track` ADD `dataUUID` binary(16) AFTER dataId; - """); - addAction(() -> { - final List datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); - final List medias = DataAccess.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track")); - for (final MediaConversion media : medias) { - for (final UUIDConversion data : datas) { - if (data.id.equals(media.dataId)) { - media.dataUUID = data.uuid; - DataAccess.update(media, media.id, List.of("dataUUID"), new OverrideTableName("track")); - break; - } - } - } - }); - - addAction(""" - DROP TABLE `playlist`; - """); - addAction(""" - DROP TABLE `playlist_link_track`; - """); - addAction(""" - ALTER TABLE `track` DROP `dataId`; - """); - addAction(""" - ALTER TABLE `track` CHANGE `dataUUID` `dataId` binary(16) NOT NULL; - """); - // Move the files... - addAction(() -> { - final List datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); - for (final UUIDConversion data : datas) { - final String origin = DataResource.getFileDataOld(data.id); - final String destination = DataResource.getFileData(data.uuid); - LOGGER.info("move file = {}", origin); - LOGGER.info(" ==> {}", destination); - Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE); - } - }); - addAction(""" - ALTER TABLE `data` DROP `id`; - """); - addAction(""" - ALTER TABLE `data` CHANGE `uuid` `id` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); - """); - addAction(""" - ALTER TABLE `data` ADD PRIMARY KEY `id` (`id`); - """); - } - } diff --git a/back/src/org/kar/karusic/migration/Migration20250104.java b/back/src/org/kar/karusic/migration/Migration20250104.java new file mode 100644 index 0000000..87f5de7 --- /dev/null +++ b/back/src/org/kar/karusic/migration/Migration20250104.java @@ -0,0 +1,144 @@ +package org.kar.karusic.migration; + +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.bson.types.ObjectId; +import org.kar.archidata.api.DataResource; +import org.kar.archidata.dataAccess.DBAccess; +import org.kar.archidata.dataAccess.options.AccessDeletedItems; +import org.kar.archidata.dataAccess.options.OverrideTableName; +import org.kar.archidata.migration.MigrationSqlStep; +import org.kar.karusic.migration.model.CoverConversion; +import org.kar.karusic.migration.model.MediaConversion; +import org.kar.karusic.migration.model.OIDConversion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Migration20250104 extends MigrationSqlStep { + private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240226.class); + + public static final int KARSO_INITIALISATION_ID = 1; + + @Override + public String getName() { + return "migration-2025-01-04: convert base from UUID to OID"; + } + + @Override + public void generateStep() throws Exception { + // Create a simple function to create objectId in the DB (for manual insertion ...) + // addAction(""" + // DELIMITER // + // + // CREATE FUNCTION generate_objectid() + // RETURNS BINARY(12) + // DETERMINISTIC + // BEGIN + // DECLARE ts BINARY(4); + // DECLARE random_part BINARY(5); + // DECLARE counter BINARY(3); + // SET ts = UNHEX(HEX(UNIX_TIMESTAMP())); + // SET random_part = UNHEX(HEX(FLOOR(RAND() * POW(2, 40)))); + // SET counter = UNHEX(HEX(FLOOR(RAND() * POW(2, 24)))); + // RETURN CONCAT(ts, random_part, counter); + // END // + // + // DELIMITER ; + // """); + addAction(""" + ALTER TABLE `data` ADD `_id` binary(12) AFTER `uuid`; + """); + addAction((final DBAccess da) -> { + final List datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); + for (final OIDConversion elem : datas) { + elem._id = new ObjectId(); + } + for (final OIDConversion elem : datas) { + da.update(elem, elem.uuid, List.of("_id"), new OverrideTableName("data")); + } + }); + final List tableToTransform = List.of("album", "artist", "gender", "track", "user"); + for (final String tableName : tableToTransform) { + addAction("ALTER TABLE `" + tableName + "` ADD `covers_oid` text NULL;"); + addAction((final DBAccess da) -> { + final List datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); + final List tableCoverTransforms = da.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName)); + LOGGER.info("Get somes data: {} {}", datas.size(), tableCoverTransforms.size()); + for (final CoverConversion tableTransform : tableCoverTransforms) { + final List values = new ArrayList<>(); + if (tableTransform.covers == null) { + continue; + } + for (final UUID link : tableTransform.covers) { + for (final OIDConversion data : datas) { + if (data.uuid.equals(link)) { + values.add(data._id); + break; + } + } + } + if (values.size() != 0) { + tableTransform.covers_oid = values; + LOGGER.info(" update: {}: {} => {}", tableTransform.id, tableTransform.covers, tableTransform.covers_oid); + da.update(tableTransform, tableTransform.id, List.of("covers_oid"), new OverrideTableName(tableName)); + } + } + }); + addAction("ALTER TABLE `" + tableName + "` DROP `covers`;"); + addAction("ALTER TABLE `" + tableName + "` CHANGE `covers_oid` `covers` text NULL;"); + } + addAction(""" + ALTER TABLE `track` ADD `dataOid` binary(12) AFTER dataId; + """); + addAction((final DBAccess da) -> { + final List datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); + final List medias = da.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track")); + for (final MediaConversion media : medias) { + for (final OIDConversion data : datas) { + if (data.uuid.equals(media.dataId)) { + media.dataOid = data._id; + da.update(media, media.id, List.of("dataOid"), new OverrideTableName("track")); + break; + } + } + } + }); + addAction(""" + ALTER TABLE `track` DROP `dataId`; + """); + addAction(""" + ALTER TABLE `track` CHANGE `dataOid` `dataId` binary(12) NOT NULL; + """); + // Move the files... + addAction((final DBAccess da) -> { + final List datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data")); + for (final OIDConversion data : datas) { + final String origin = DataResource.getFileDataOld(data.uuid); + final String destination = DataResource.getFileData(data._id); + LOGGER.info("move file = {}", origin); + LOGGER.info(" ==> {}", destination); + try { + Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE); + } catch (final NoSuchFileException ex) { + LOGGER.warn("Fail to move file : {}", ex.getMessage()); + } + } + }); + addAction(""" + ALTER TABLE `data` DROP `uuid`; + """); + // addAction(""" + // ALTER TABLE `data` CHANGE `_id` `_id` BINARY(12) DEFAULT (generate_objectid()); + // """); + addAction(""" + ALTER TABLE `data` ADD PRIMARY KEY `_id` (`_id`); + """); + } + +} diff --git a/back/src/org/kar/karusic/migration/Migration20250105.java b/back/src/org/kar/karusic/migration/Migration20250105.java new file mode 100644 index 0000000..1668394 --- /dev/null +++ b/back/src/org/kar/karusic/migration/Migration20250105.java @@ -0,0 +1,31 @@ +package org.kar.karusic.migration; + +import org.kar.archidata.migration.MigrationSqlStep; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Migration20250105 extends MigrationSqlStep { + private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240907.class); + + public static final int KARSO_INITIALISATION_ID = 1; + + @Override + public String getName() { + return "migration-2025-01-05: remove old UUID"; + } + + @Override + public void generateStep() throws Exception { + // addAction(""" + // ALTER TABLE `data` DROP INDEX `PRIMARY`; + // """); + // addAction(""" + // ALTER TABLE `data` CHANGE `id` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE)); + // """); + // addAction(""" + // ALTER TABLE `data` ADD PRIMARY KEY `uuid` (`uuid`); + // """); + + } + +} diff --git a/back/src/org/kar/karusic/migration/model/CoverConversion.java b/back/src/org/kar/karusic/migration/model/CoverConversion.java index 6015f69..e003398 100644 --- a/back/src/org/kar/karusic/migration/model/CoverConversion.java +++ b/back/src/org/kar/karusic/migration/model/CoverConversion.java @@ -3,6 +3,7 @@ package org.kar.karusic.migration.model; import java.util.List; import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataJson; import jakarta.persistence.Id; @@ -12,4 +13,6 @@ public class CoverConversion { public Long id = null; @DataJson public List covers = null; + @DataJson + public List covers_oid = null; } diff --git a/back/src/org/kar/karusic/migration/model/MediaConversion.java b/back/src/org/kar/karusic/migration/model/MediaConversion.java index 09eb3a9..00cd5d8 100644 --- a/back/src/org/kar/karusic/migration/model/MediaConversion.java +++ b/back/src/org/kar/karusic/migration/model/MediaConversion.java @@ -2,11 +2,13 @@ package org.kar.karusic.migration.model; import java.util.UUID; +import org.bson.types.ObjectId; + import jakarta.persistence.Id; public class MediaConversion { @Id public Long id = null; - public Long dataId = null; - public UUID dataUUID = null; + public UUID dataId = null; + public ObjectId dataOid = null; } diff --git a/back/src/org/kar/karusic/migration/model/UUIDConversion.java b/back/src/org/kar/karusic/migration/model/OIDConversion.java similarity index 59% rename from back/src/org/kar/karusic/migration/model/UUIDConversion.java rename to back/src/org/kar/karusic/migration/model/OIDConversion.java index 475711e..387256d 100644 --- a/back/src/org/kar/karusic/migration/model/UUIDConversion.java +++ b/back/src/org/kar/karusic/migration/model/OIDConversion.java @@ -2,10 +2,12 @@ package org.kar.karusic.migration.model; import java.util.UUID; +import org.bson.types.ObjectId; + import jakarta.persistence.Id; -public class UUIDConversion { +public class OIDConversion { @Id - public Long id = null; public UUID uuid = null; + public ObjectId _id = null; } diff --git a/back/src/org/kar/karusic/model/Album.java b/back/src/org/kar/karusic/model/Album.java index 963bf14..954f616 100644 --- a/back/src/org/kar/karusic/model/Album.java +++ b/back/src/org/kar/karusic/model/Album.java @@ -2,8 +2,8 @@ package org.kar.karusic.model; import java.time.LocalDate; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.options.CheckJPA; @@ -12,11 +12,13 @@ import org.kar.archidata.model.GenericDataSoftDelete; import com.fasterxml.jackson.annotation.JsonInclude; +import dev.morphia.annotations.Entity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Table; +@Entity("Album") @Table(name = "album") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) @@ -34,6 +36,6 @@ public class Album extends GenericDataSoftDelete { @Schema(description = "List of Id of the specific covers") @DataJson(targetEntity = Data.class) @Nullable - public List covers = null; + public List covers = null; public LocalDate publication = null; } diff --git a/back/src/org/kar/karusic/model/Artist.java b/back/src/org/kar/karusic/model/Artist.java index d9e733c..bea6ef8 100644 --- a/back/src/org/kar/karusic/model/Artist.java +++ b/back/src/org/kar/karusic/model/Artist.java @@ -2,8 +2,8 @@ package org.kar.karusic.model; import java.time.LocalDate; import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.options.CheckJPA; @@ -12,11 +12,13 @@ import org.kar.archidata.model.GenericDataSoftDelete; import com.fasterxml.jackson.annotation.JsonInclude; +import dev.morphia.annotations.Entity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Table; +@Entity("Artist") @Table(name = "artist") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) @@ -34,7 +36,7 @@ public class Artist extends GenericDataSoftDelete { @Schema(description = "List of Id of the specific covers") @DataJson(targetEntity = Data.class) @Nullable - public List covers = null; + public List covers = null; @Column(length = 256) public String firstName = null; @Column(length = 256) diff --git a/back/src/org/kar/karusic/model/Gender.java b/back/src/org/kar/karusic/model/Gender.java index 0fdd860..3c92730 100644 --- a/back/src/org/kar/karusic/model/Gender.java +++ b/back/src/org/kar/karusic/model/Gender.java @@ -13,8 +13,8 @@ CREATE TABLE `node` ( */ import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.options.CheckJPA; @@ -23,11 +23,13 @@ import org.kar.archidata.model.GenericDataSoftDelete; import com.fasterxml.jackson.annotation.JsonInclude; +import dev.morphia.annotations.Entity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Table; +@Entity("Gender") @Table(name = "gender") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) @@ -45,6 +47,13 @@ public class Gender extends GenericDataSoftDelete { @Schema(description = "List of Id of the specific covers") @DataJson(targetEntity = Data.class) @Nullable - public List covers = null; + public List covers = null; + + public Gender() {} + + public Gender(final Long id, final String name) { + this.id = id; + this.name = name; + } } diff --git a/back/src/org/kar/karusic/model/Playlist.java b/back/src/org/kar/karusic/model/Playlist.java index 990bc44..e7a6395 100644 --- a/back/src/org/kar/karusic/model/Playlist.java +++ b/back/src/org/kar/karusic/model/Playlist.java @@ -13,8 +13,8 @@ CREATE TABLE `node` ( */ import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.options.CheckJPA; @@ -23,6 +23,7 @@ import org.kar.archidata.model.GenericDataSoftDelete; import com.fasterxml.jackson.annotation.JsonInclude; +import dev.morphia.annotations.Entity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.Nullable; import jakarta.persistence.Column; @@ -30,6 +31,7 @@ import jakarta.persistence.FetchType; import jakarta.persistence.ManyToMany; import jakarta.persistence.Table; +@Entity("Playlist") @Table(name = "playlist") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) @@ -47,7 +49,7 @@ public class Playlist extends GenericDataSoftDelete { @Schema(description = "List of Id of the specific covers") @DataJson(targetEntity = Data.class) @Nullable - public List covers = null; + public List covers = null; @ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class) - public List tracks = null; + public List tracks = null; } diff --git a/back/src/org/kar/karusic/model/Track.java b/back/src/org/kar/karusic/model/Track.java index 1eba2e3..c765e5b 100644 --- a/back/src/org/kar/karusic/model/Track.java +++ b/back/src/org/kar/karusic/model/Track.java @@ -13,8 +13,8 @@ CREATE TABLE `node` ( */ import java.util.List; -import java.util.UUID; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.options.CheckJPA; @@ -23,11 +23,13 @@ import org.kar.archidata.model.GenericDataSoftDelete; import com.fasterxml.jackson.annotation.JsonInclude; +import dev.morphia.annotations.Entity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Table; +@Entity("Track") @Table(name = "track") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) @@ -46,11 +48,11 @@ public class Track extends GenericDataSoftDelete { @Schema(description = "List of Id of the specific covers") @DataJson(targetEntity = Data.class) @Nullable - public List covers = null; + public List covers = null; public Long genderId = null; public Long albumId = null; public Long track = null; - public UUID dataId = null; + public ObjectId dataId = null; // @ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class) @DataJson @Column(length = 0) diff --git a/back/src/resources/logback.xml b/back/src/resources/logback.xml new file mode 100644 index 0000000..8a1d304 --- /dev/null +++ b/back/src/resources/logback.xml @@ -0,0 +1,18 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger - %msg%n + + + + + + + + + diff --git a/back/src/resources/simplelogger.properties b/back/src/resources/simplelogger.properties index 4314b58..4192d0a 100644 --- a/back/src/resources/simplelogger.properties +++ b/back/src/resources/simplelogger.properties @@ -3,12 +3,14 @@ # 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 +org.slf4j.simpleLogger.defaultLogLevel=INFO # 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= +org.slf4j.simpleLogger.log.org.kar.archidata=TRACE +org.slf4j.simpleLogger.log.org.kar.karusic=TRACE # 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. @@ -32,4 +34,9 @@ org.slf4j.simpleLogger.showThreadName=true # Defaults to false. #org.slf4j.simpleLogger.showShortLogName=false +# Utilise les codes ANSI pour la couleur +org.slf4j.simpleLogger.warnColor=\u001B[33m +org.slf4j.simpleLogger.errorColor=\u001B[31m +org.slf4j.simpleLogger.infoColor=\u001B[32m +org.slf4j.simpleLogger.debugColor=\u001B[34m diff --git a/back/test/src/test/kar/karusic/ConfigureDb.java b/back/test/src/test/kar/karusic/ConfigureDb.java new file mode 100644 index 0000000..4f17e07 --- /dev/null +++ b/back/test/src/test/kar/karusic/ConfigureDb.java @@ -0,0 +1,126 @@ +package test.kar.karusic; + +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.karusic.model.Album; +import org.kar.karusic.model.Artist; +import org.kar.karusic.model.Gender; +import org.kar.karusic.model.Playlist; +import org.kar.karusic.model.Track; +import org.kar.karusic.model.UserKarusic; +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; + } + final List> listObject = List.of( // + Album.class, // + Artist.class, // + Gender.class, // + Playlist.class, // + Track.class, // + UserKarusic.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_karusic_db"; + ConfigBaseVariable.dbPort = "3906"; + ConfigBaseVariable.dbUser = "root"; + } else if ("MONGO".equalsIgnoreCase(modeTest)) { + ConfigBaseVariable.dbType = "mongo"; + ConfigBaseVariable.bdDatabase = "test_karusic_db"; + } else { + // User local modification ... + ConfigBaseVariable.bdDatabase = "test_karusic_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(); + } +} diff --git a/back/test/src/test/kar/karusic/TestBase.java b/back/test/src/test/kar/karusic/TestBase.java index 5316eed..d315a4c 100644 --- a/back/test/src/test/kar/karusic/TestBase.java +++ b/back/test/src/test/kar/karusic/TestBase.java @@ -7,10 +7,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.ExtendWith; -import org.kar.archidata.db.DBEntry; import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.RESTApi; -import org.kar.karusic.migration.Initialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,31 +25,16 @@ public class TestBase { @BeforeAll public static void configureWebServer() throws Exception { + ConfigureDb.configure(); LOGGER.info("configure server ..."); webInterface = new WebLauncherTest(); LOGGER.info("Clean previous table"); - try { - Initialization.dropAll(); - } catch (final Exception ex) { - ex.printStackTrace(); - LOGGER.error("plop: {}", ex.getLocalizedMessage()); - throw ex; - } - - LOGGER.info("Create DB"); - try { - webInterface.migrateDB(); - } catch (final Exception ex) { - ex.printStackTrace(); - LOGGER.error("Detect an error: {}", ex.getMessage()); - } LOGGER.info("Start REST (BEGIN)"); webInterface.process(); LOGGER.info("Start REST (DONE)"); api = new RESTApi(ConfigBaseVariable.apiAdress); - api.setToken(Common.USER_TOKEN); - + api.setToken(Common.ADMIN_TOKEN); } @AfterAll @@ -59,9 +42,7 @@ public class TestBase { LOGGER.info("Kill the web server"); webInterface.stop(); webInterface = null; - LOGGER.info("Remove the test db"); - DBEntry.closeAllForceMode(); - ConfigBaseVariable.clearAllValue(); + ConfigureDb.clear(); } } diff --git a/back/test/src/test/kar/karusic/TestMongoDb.java b/back/test/src/test/kar/karusic/TestMongoDb.java new file mode 100644 index 0000000..f24a63a --- /dev/null +++ b/back/test/src/test/kar/karusic/TestMongoDb.java @@ -0,0 +1,61 @@ +package test.kar.karusic; + +import static org.bson.codecs.configuration.CodecRegistries.fromProviders; +import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; + +import java.io.IOException; + +import org.bson.codecs.configuration.CodecRegistry; +import org.bson.codecs.pojo.PojoCodecProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kar.karusic.model.Track; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; + +@ExtendWith(StepwiseExtension.class) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class TestMongoDb { + final static private Logger LOGGER = LoggerFactory.getLogger(TestMongoDb.class); + + @BeforeAll + public static void configureWebServer() throws Exception {} + + @AfterAll + public static void removeDataBase() throws IOException { + + } + + @Order(1) + @Test + public void testCreateTable() throws Exception { + final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017");// System.getProperty("mongodb.uri")); + // Configure the CodecRegistry to include a codec to handle the translation to and from BSON for our POJOs. + final CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build()); + // Add the default codec registry, which contains all the default codecs. They can handle all the major types in + // Java-like Boolean, Double, String, BigDecimal, etc. + final CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry); + // Wrap all my settings together using MongoClientSettings. + final MongoClientSettings clientSettings = MongoClientSettings.builder().applyConnectionString(connectionString).codecRegistry(codecRegistry).build(); + // Initiate the connection with MongoDB. + try (MongoClient mongoClient = MongoClients.create(clientSettings)) { + final MongoDatabase db = mongoClient.getDatabase("sample_training"); + final MongoCollection grades = db.getCollection("Track", Track.class); + + } + + } + +} diff --git a/env_dev/docker-compose.yaml b/env_dev/docker-compose.yaml index 49351f6..c09d871 100644 --- a/env_dev/docker-compose.yaml +++ b/env_dev/docker-compose.yaml @@ -19,6 +19,7 @@ services: kar_mongodb_service: image: mongo:latest + restart: always environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: base_db_password @@ -27,19 +28,6 @@ services: volumes: - ./dataMongo:/data/db - mongo_express_service: - image: mongo-express - restart: always - ports: - - 8081:8081 - links: - - kar_mongodb_service:db - environment: - ME_CONFIG_MONGODB_ADMINUSERNAME: root - ME_CONFIG_MONGODB_ADMINPASSWORD: base_db_password - ME_CONFIG_MONGODB_URL: mongodb://root:base_db_password@db:27017/ - ME_CONFIG_BASICAUTH: false - kar_adminer_service: image: adminer:latest restart: always @@ -52,3 +40,17 @@ services: ports: - 4079:8080 mem_limit: 50m + + mongo_express_service: + image: mongo-express + restart: always + ports: + - 4077:8081 + links: + - kar_mongodb_service:db + environment: + ME_CONFIG_MONGODB_ADMINUSERNAME: root + ME_CONFIG_MONGODB_ADMINPASSWORD: base_db_password + ME_CONFIG_MONGODB_URL: mongodb://root:base_db_password@db:27017/ + ME_CONFIG_BASICAUTH: false + diff --git a/front/src/back-api/api/album-resource.ts b/front/src/back-api/api/album-resource.ts index 3cb986e..c3a2913 100644 --- a/front/src/back-api/api/album-resource.ts +++ b/front/src/back-api/api/album-resource.ts @@ -22,30 +22,6 @@ import { export namespace AlbumResource { - /** - * Add a Track on a specific album - */ - export function addTrack({ - restConfig, - params, - }: { - restConfig: RESTConfig, - params: { - trackId: Long, - id: Long, - }, - }): Promise { - return RESTRequestJson({ - restModel: { - endPoint: "/album/{id}/track/{trackId}", - requestType: HTTPRequestModel.POST, - contentType: HTTPMimeType.MULTIPART, - accept: HTTPMimeType.JSON, - }, - restConfig, - params, - }, isAlbum); - }; /** * Get a specific Album with his ID */ @@ -192,30 +168,6 @@ export namespace AlbumResource { params, }, isAlbum); }; - /** - * Remove a Track on a specific album - */ - export function removeTrack({ - restConfig, - params, - }: { - restConfig: RESTConfig, - params: { - trackId: Long, - id: Long, - }, - }): Promise { - return RESTRequestJson({ - restModel: { - endPoint: "/album/{id}/track/{trackId}", - requestType: HTTPRequestModel.DELETE, - contentType: HTTPMimeType.TEXT_PLAIN, - accept: HTTPMimeType.JSON, - }, - restConfig, - params, - }, isAlbum); - }; /** * Add a cover on a specific album */ diff --git a/front/src/back-api/api/artist-resource.ts b/front/src/back-api/api/artist-resource.ts index bef0694..94ca392 100644 --- a/front/src/back-api/api/artist-resource.ts +++ b/front/src/back-api/api/artist-resource.ts @@ -15,7 +15,7 @@ import { Artist, ArtistWrite, Long, - UUID, + ObjectId, ZodArtist, isArtist, } from "../model"; @@ -135,7 +135,7 @@ export namespace ArtistResource { }: { restConfig: RESTConfig, params: { - coverId: UUID, + coverId: ObjectId, id: Long, }, }): Promise { diff --git a/front/src/back-api/api/data-resource.ts b/front/src/back-api/api/data-resource.ts index 61891c1..7b32bb2 100644 --- a/front/src/back-api/api/data-resource.ts +++ b/front/src/back-api/api/data-resource.ts @@ -10,7 +10,7 @@ import { } from "../rest-tools"; import { - UUID, + ObjectId, } from "../model"; export namespace DataResource { @@ -30,13 +30,13 @@ export namespace DataResource { }, params: { name: string, - uuid: UUID, + oid: ObjectId, }, data: string, }): Promise { return RESTRequestJson({ restModel: { - endPoint: "/data/{uuid}/{name}", + endPoint: "/data/{oid}/{name}", requestType: HTTPRequestModel.GET, }, restConfig, @@ -59,13 +59,13 @@ export namespace DataResource { Authorization?: string, }, params: { - uuid: UUID, + oid: ObjectId, }, data: string, }): Promise { return RESTRequestJson({ restModel: { - endPoint: "/data/{uuid}", + endPoint: "/data/{oid}", requestType: HTTPRequestModel.GET, }, restConfig, @@ -88,13 +88,13 @@ export namespace DataResource { Authorization?: string, }, params: { - uuid: UUID, + oid: ObjectId, }, data: string, }): Promise { return RESTRequestJson({ restModel: { - endPoint: "/data/thumbnail/{uuid}", + endPoint: "/data/thumbnail/{oid}", requestType: HTTPRequestModel.GET, }, restConfig, diff --git a/front/src/back-api/api/gender-resource.ts b/front/src/back-api/api/gender-resource.ts index 56cfe03..dd9b7a9 100644 --- a/front/src/back-api/api/gender-resource.ts +++ b/front/src/back-api/api/gender-resource.ts @@ -15,7 +15,7 @@ import { Gender, GenderWrite, Long, - UUID, + ObjectId, ZodGender, isGender, } from "../model"; @@ -135,7 +135,7 @@ export namespace GenderResource { }: { restConfig: RESTConfig, params: { - coverId: UUID, + coverId: ObjectId, id: Long, }, }): Promise { diff --git a/front/src/back-api/api/playlist-resource.ts b/front/src/back-api/api/playlist-resource.ts index e8a273b..8c6e49a 100644 --- a/front/src/back-api/api/playlist-resource.ts +++ b/front/src/back-api/api/playlist-resource.ts @@ -12,9 +12,9 @@ import { import { z as zod } from "zod" import { Long, + ObjectId, Playlist, PlaylistWrite, - UUID, ZodPlaylist, isPlaylist, } from "../model"; @@ -155,7 +155,7 @@ export namespace PlaylistResource { }: { restConfig: RESTConfig, params: { - coverId: UUID, + coverId: ObjectId, id: Long, }, }): Promise { diff --git a/front/src/back-api/api/track-resource.ts b/front/src/back-api/api/track-resource.ts index 3a91a3d..eade9d4 100644 --- a/front/src/back-api/api/track-resource.ts +++ b/front/src/back-api/api/track-resource.ts @@ -13,9 +13,9 @@ import { import { z as zod } from "zod" import { Long, + ObjectId, Track, TrackWrite, - UUID, ZodTrack, isTrack, } from "../model"; @@ -156,7 +156,7 @@ export namespace TrackResource { }: { restConfig: RESTConfig, params: { - coverId: UUID, + coverId: ObjectId, id: Long, }, }): Promise { diff --git a/front/src/back-api/model/album.ts b/front/src/back-api/model/album.ts index dbdda5d..1f1c6e3 100644 --- a/front/src/back-api/model/album.ts +++ b/front/src/back-api/model/album.ts @@ -3,7 +3,7 @@ */ import { z as zod } from "zod"; -import {ZodUUID} from "./uuid"; +import {ZodObjectId} from "./object-id"; import {ZodLocalDate} from "./local-date"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; @@ -13,7 +13,7 @@ export const ZodAlbum = ZodGenericDataSoftDelete.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).optional(), + covers: zod.array(ZodObjectId).optional(), publication: ZodLocalDate.optional(), }); @@ -35,7 +35,7 @@ export const ZodAlbumWrite = ZodGenericDataSoftDeleteWrite.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).nullable().optional(), + covers: zod.array(ZodObjectId).nullable().optional(), publication: ZodLocalDate.nullable().optional(), }); diff --git a/front/src/back-api/model/artist.ts b/front/src/back-api/model/artist.ts index 8c03b16..5e66c0a 100644 --- a/front/src/back-api/model/artist.ts +++ b/front/src/back-api/model/artist.ts @@ -3,7 +3,7 @@ */ import { z as zod } from "zod"; -import {ZodUUID} from "./uuid"; +import {ZodObjectId} from "./object-id"; import {ZodLocalDate} from "./local-date"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; @@ -13,7 +13,7 @@ export const ZodArtist = ZodGenericDataSoftDelete.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).optional(), + covers: zod.array(ZodObjectId).optional(), firstName: zod.string().max(256).optional(), surname: zod.string().max(256).optional(), birth: ZodLocalDate.optional(), @@ -38,7 +38,7 @@ export const ZodArtistWrite = ZodGenericDataSoftDeleteWrite.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).nullable().optional(), + covers: zod.array(ZodObjectId).nullable().optional(), firstName: zod.string().max(256).nullable().optional(), surname: zod.string().max(256).nullable().optional(), birth: ZodLocalDate.nullable().optional(), diff --git a/front/src/back-api/model/gender.ts b/front/src/back-api/model/gender.ts index 765e713..1c65555 100644 --- a/front/src/back-api/model/gender.ts +++ b/front/src/back-api/model/gender.ts @@ -3,7 +3,7 @@ */ import { z as zod } from "zod"; -import {ZodUUID} from "./uuid"; +import {ZodObjectId} from "./object-id"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; export const ZodGender = ZodGenericDataSoftDelete.extend({ @@ -12,7 +12,7 @@ export const ZodGender = ZodGenericDataSoftDelete.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).optional(), + covers: zod.array(ZodObjectId).optional(), }); @@ -33,7 +33,7 @@ export const ZodGenderWrite = ZodGenericDataSoftDeleteWrite.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).nullable().optional(), + covers: zod.array(ZodObjectId).nullable().optional(), }); diff --git a/front/src/back-api/model/index.ts b/front/src/back-api/model/index.ts index fef4de1..2493ae1 100644 --- a/front/src/back-api/model/index.ts +++ b/front/src/back-api/model/index.ts @@ -12,6 +12,7 @@ export * from "./integer" export * from "./iso-date" export * from "./local-date" export * from "./long" +export * from "./object-id" export * from "./part-right" export * from "./playlist" export * from "./rest-error-response" diff --git a/front/src/back-api/model/object-id.ts b/front/src/back-api/model/object-id.ts new file mode 100644 index 0000000..ace0bd1 --- /dev/null +++ b/front/src/back-api/model/object-id.ts @@ -0,0 +1,8 @@ +/** + * Interface of the server (auto-generated code) + */ +import { z as zod } from "zod"; + + +export const ZodObjectId = zod.string().length(24, "Invalid ObjectId length").regex(/^[a-fA-F0-9]{24}$/, "Invalid ObjectId format"); +export type ObjectId = zod.infer; diff --git a/front/src/back-api/model/playlist.ts b/front/src/back-api/model/playlist.ts index c39932e..6c8287f 100644 --- a/front/src/back-api/model/playlist.ts +++ b/front/src/back-api/model/playlist.ts @@ -3,8 +3,7 @@ */ import { z as zod } from "zod"; -import {ZodUUID} from "./uuid"; -import {ZodLong} from "./long"; +import {ZodObjectId} from "./object-id"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; export const ZodPlaylist = ZodGenericDataSoftDelete.extend({ @@ -13,8 +12,8 @@ export const ZodPlaylist = ZodGenericDataSoftDelete.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).optional(), - tracks: zod.array(ZodLong), + covers: zod.array(ZodObjectId).optional(), + tracks: zod.array(ZodObjectId), }); @@ -35,8 +34,8 @@ export const ZodPlaylistWrite = ZodGenericDataSoftDeleteWrite.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).nullable().optional(), - tracks: zod.array(ZodLong).optional(), + covers: zod.array(ZodObjectId).nullable().optional(), + tracks: zod.array(ZodObjectId).optional(), }); diff --git a/front/src/back-api/model/track.ts b/front/src/back-api/model/track.ts index c2b0fb8..8445f2e 100644 --- a/front/src/back-api/model/track.ts +++ b/front/src/back-api/model/track.ts @@ -3,7 +3,7 @@ */ import { z as zod } from "zod"; -import {ZodUUID} from "./uuid"; +import {ZodObjectId} from "./object-id"; import {ZodLong} from "./long"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; @@ -13,11 +13,11 @@ export const ZodTrack = ZodGenericDataSoftDelete.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).optional(), + covers: zod.array(ZodObjectId).optional(), genderId: ZodLong.optional(), albumId: ZodLong.optional(), track: ZodLong.optional(), - dataId: ZodUUID.optional(), + dataId: ZodObjectId.optional(), artists: zod.array(ZodLong), }); @@ -39,11 +39,11 @@ export const ZodTrackWrite = ZodGenericDataSoftDeleteWrite.extend({ /** * List of Id of the specific covers */ - covers: zod.array(ZodUUID).nullable().optional(), + covers: zod.array(ZodObjectId).nullable().optional(), genderId: ZodLong.nullable().optional(), albumId: ZodLong.nullable().optional(), track: ZodLong.nullable().optional(), - dataId: ZodUUID.nullable().optional(), + dataId: ZodObjectId.nullable().optional(), artists: zod.array(ZodLong).optional(), }); diff --git a/front/src/back-api/model/user.ts b/front/src/back-api/model/user.ts index 0e04c36..d668bc6 100644 --- a/front/src/back-api/model/user.ts +++ b/front/src/back-api/model/user.ts @@ -8,11 +8,10 @@ import {ZodUUID} from "./uuid"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; export const ZodUser = ZodGenericDataSoftDelete.extend({ - login: zod.string().max(128).optional(), + login: zod.string().min(3).max(128), lastConnection: ZodTimestamp.optional(), - admin: zod.boolean(), blocked: zod.boolean(), - removed: zod.boolean(), + blockedReason: zod.string().max(512).optional(), /** * List of Id of the specific covers */ @@ -32,11 +31,10 @@ export function isUser(data: any): data is User { } } export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({ - login: zod.string().max(128).nullable().optional(), + login: zod.string().min(3).max(128).optional(), lastConnection: ZodTimestamp.nullable().optional(), - admin: zod.boolean(), blocked: zod.boolean(), - removed: zod.boolean(), + blockedReason: zod.string().max(512).nullable().optional(), /** * List of Id of the specific covers */ diff --git a/front/src/back-api/rest-tools.ts b/front/src/back-api/rest-tools.ts index 2fac824..d269ed7 100644 --- a/front/src/back-api/rest-tools.ts +++ b/front/src/back-api/rest-tools.ts @@ -7,11 +7,15 @@ import { RestErrorResponse, isRestErrorResponse } from "./model"; export enum HTTPRequestModel { + ARCHIVE = "ARCHIVE", DELETE = "DELETE", + HEAD = "HEAD", GET = "GET", + OPTION = "OPTION", PATCH = "PATCH", POST = "POST", PUT = "PUT", + RESTORE = "RESTORE", } export enum HTTPMimeType { ALL = "*/*", @@ -248,9 +252,14 @@ export function RESTRequest({ if (restModel.accept !== undefined) { headers["Accept"] = restModel.accept; } - if (restModel.requestType !== HTTPRequestModel.GET) { + if (restModel.requestType !== HTTPRequestModel.GET && + restModel.requestType !== HTTPRequestModel.ARCHIVE && + restModel.requestType !== HTTPRequestModel.RESTORE + ) { // if Get we have not a content type, the body is empty - if (restModel.contentType !== HTTPMimeType.MULTIPART) { + if (restModel.contentType !== HTTPMimeType.MULTIPART && + restModel.contentType !== undefined + ) { // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" headers["Content-Type"] = restModel.contentType; } diff --git a/front/src/components/Cover.tsx b/front/src/components/Cover.tsx index 8325429..c565928 100644 --- a/front/src/components/Cover.tsx +++ b/front/src/components/Cover.tsx @@ -5,9 +5,10 @@ import { Image } from '@chakra-ui/react'; import { DataUrlAccess } from '@/utils/data-url-access'; import { Icon } from './Icon'; +import { ObjectId } from '@/back-api'; export type CoversProps = BoxProps & { - data?: string[]; + data?: ObjectId[]; size?: StyleProps["width"]; iconEmpty?: As; slideshow?: boolean; diff --git a/front/src/components/SearchInput.tsx b/front/src/components/SearchInput.tsx index c1e8b66..55fdec0 100644 --- a/front/src/components/SearchInput.tsx +++ b/front/src/components/SearchInput.tsx @@ -1,11 +1,9 @@ import { useState } from 'react'; -import React from 'react'; import { Input, InputGroup, InputLeftElement, - useOutsideClick, } from '@chakra-ui/react'; import { MdSearch } from 'react-icons/md'; diff --git a/front/src/scene/home/HomePage.tsx b/front/src/scene/home/HomePage.tsx index dcdbf9f..7eb308b 100644 --- a/front/src/scene/home/HomePage.tsx +++ b/front/src/scene/home/HomePage.tsx @@ -1,7 +1,7 @@ import { ReactElement } from 'react'; import { Center, Flex, Text, Wrap, WrapItem } from '@chakra-ui/react'; -import { LuCrown, LuDisc3, LuEar, LuFileAudio, LuUser } from 'react-icons/lu'; +import { LuCrown, LuDisc3, LuEar, LuFileAudio } from 'react-icons/lu'; import { MdGroup } from 'react-icons/md'; import { useNavigate } from 'react-router-dom'; diff --git a/front/src/scene/track/TrackRoutes.tsx b/front/src/scene/track/TrackRoutes.tsx index 4e377e7..d118503 100644 --- a/front/src/scene/track/TrackRoutes.tsx +++ b/front/src/scene/track/TrackRoutes.tsx @@ -1,7 +1,6 @@ import { Navigate, Route, Routes } from 'react-router-dom'; import { Error404 } from '@/errors'; -import { ArtistAlbumDetailPage } from '@/scene/artist/ArtistAlbumDetailPage'; import { TrackSelectionPage } from '@/scene/track/TrackSelectionPage'; import { TracksStartLetterDetailPage } from '@/scene/track/TracksStartLetterDetailPage';