Compare commits
	
		
			29 Commits
		
	
	
		
			feat_raw_r
			...
			v1.2.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 061fc51138 | ||
|   | c5b714b609 | ||
|   | d23f1a945c | ||
| 50f0c903f4 | |||
| 15dfdd8605 | |||
| ba7b6e4755 | |||
| 3beafab7e1 | |||
| 9cf41dd094 | |||
| 4caec9a54a | |||
| 83f8ec0e9b | |||
| 4993c17136 | |||
| 401e2ce3c5 | |||
| 693d59ab68 | |||
| 4eff2e55ef | |||
| 1e890f9524 | |||
| dbb2527cb8 | |||
| d65faa8810 | |||
| 9c9476b052 | |||
| 3e92c2b74a | |||
| a7134c01ed | |||
| 88b27e5f39 | |||
| eaf0f5688e | |||
| 4ebfa4e2ca | |||
| c65e7d5e25 | |||
| de61cc156f | |||
| 4d18438914 | |||
| 80dfabcf48 | |||
| 83bfeda4ca | |||
| c489fabb77 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -65,3 +65,4 @@ __pycache__ | ||||
| .design/ | ||||
| .vscode/ | ||||
| front/storybook-static | ||||
| back/bin | ||||
|   | ||||
							
								
								
									
										15
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -6,7 +6,7 @@ | ||||
| FROM archlinux:base-devel AS common | ||||
| # update system | ||||
| RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | ||||
|     && pacman -S --noconfirm jdk-openjdk \ | ||||
|     && pacman -S --noconfirm jdk-openjdk wget\ | ||||
|     && pacman -Scc --noconfirm | ||||
|  | ||||
| WORKDIR /tmp | ||||
| @@ -53,14 +53,15 @@ RUN pnpm install --prod=false | ||||
| FROM dependency_front AS load_sources_front | ||||
|  | ||||
| # JUST to get the vertion of the application and his sha... | ||||
| COPY front/build.js \ | ||||
|   front/version.txt \ | ||||
| COPY \ | ||||
|   front/tsconfig.json \ | ||||
|   front/tsconfig.node.json \ | ||||
|   front/vite.config.mts \ | ||||
|   front/index.html \ | ||||
|   ./ | ||||
|  | ||||
| COPY front/public ./public | ||||
| COPY front/public/icons ./public/icons | ||||
| COPY front/src ./src | ||||
|  | ||||
| #We are not in prod mode ==> we need to overwrite the production env. | ||||
| @@ -99,8 +100,14 @@ ENV LANG C.UTF-8 | ||||
| COPY --from=build_back /tmp/out/maven/*.jar /application/application.jar | ||||
| COPY --from=build_front /tmp/dist /application/front/ | ||||
|  | ||||
| # COPY front/public/icons /application/front/public/icons | ||||
| # COPY front/public/icons /application/front/icons | ||||
| WORKDIR /application/ | ||||
|  | ||||
| EXPOSE 80 | ||||
|  | ||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karusic.WebLauncher"] | ||||
| # To verify health-check: docker inspect --format "{{json .State.Health }}" YOUR_SERVICE_NAME | jq | ||||
| HEALTHCHECK --start-period=10s --start-interval=2s --interval=30s --timeout=5s --retries=10 \ | ||||
|    CMD wget --no-verbose --tries=1 --spider http://localhost:80/api/health_check || exit 1 | ||||
|  | ||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.atriasoft.karusic.WebLauncher"] | ||||
|   | ||||
							
								
								
									
										79
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| Karideo | ||||
| Karusic | ||||
| ======= | ||||
|  | ||||
| **K**angaroo **A**nd **R**abbit (m)usic is a simple framework to propose music streaming for personal network | ||||
| @@ -6,38 +6,71 @@ Karideo | ||||
| Run in local: | ||||
| ============= | ||||
|  | ||||
| so simple... | ||||
| Start tools | ||||
| ----------- | ||||
|  | ||||
| Start the server basic interfaces: (DB(mySQL), Adminer) | ||||
|  | ||||
| ```{.bash} | ||||
| # start the Bdd interface (no big data > 50Mo) | ||||
| cd bdd | ||||
| docker-compose up -d | ||||
| # start the REST API | ||||
| cd back | ||||
| docker-compose up -d | ||||
| # start the front API | ||||
| cd ../front | ||||
| docker-compose up -d | ||||
| docker compose -f env_dev/docker-compose.yaml up -d | ||||
| ``` | ||||
|  | ||||
| Start the Back-end: | ||||
| ------------------- | ||||
|  | ||||
| convert in an angular application:  | ||||
| https://betterprogramming.pub/how-to-convert-your-angular-application-to-a-native-mobile-app-android-and-ios-c212b38976df | ||||
| backend is developed in JAVA | ||||
|  | ||||
|  | ||||
| Link with the external sub-library (front) | ||||
| ------------------------------------------ | ||||
|  | ||||
| Link: | ||||
| The first step is configuring your JAVA version (or select the JVM with the OS) | ||||
| ```bash | ||||
| cd front | ||||
| pnpm run link_kar_cw | ||||
| export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH | ||||
| ``` | ||||
|  | ||||
| un-link: | ||||
| Install the dependency: | ||||
| ```bash | ||||
| mvn install | ||||
| ``` | ||||
|  | ||||
| Run the test | ||||
| ```bash | ||||
| mvn test | ||||
| ``` | ||||
|  | ||||
| Install it for external use | ||||
| ```bash | ||||
| mvn install | ||||
| ``` | ||||
|  | ||||
| Execute the local server: | ||||
| ```bash | ||||
| mvn exec:java@dev-mode | ||||
| ``` | ||||
|  | ||||
| Start the Front-end: | ||||
| -------------------- | ||||
|  | ||||
| backend is developed in JAVA | ||||
| ```bash | ||||
| cd front | ||||
| pnpm run unlink_kar_cw | ||||
| pnpm install | ||||
| pnpm dev | ||||
| ``` | ||||
|  | ||||
| Display the result: | ||||
| ------------------- | ||||
|  | ||||
| [show the webpage: http://localhost:4203](http://localhost:4203) | ||||
|  | ||||
| Some other dev tools: | ||||
| ===================== | ||||
|  | ||||
| Format code: | ||||
| ------------ | ||||
|  | ||||
| ```bash | ||||
| export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH | ||||
| mvn formatter:format | ||||
| mvn test | ||||
| ``` | ||||
|  | ||||
| Tools in production mode | ||||
| @@ -49,7 +82,7 @@ Changing the Log Level | ||||
| In a production environment, you can adjust the log level to help diagnose bugs more effectively. | ||||
|  | ||||
| The available log levels are: | ||||
| | **Log Level Tag** | **org.kar.karusic** | **org.kar.archidata** | **other** | | ||||
| | **Log Level Tag** | **org.atriasoft.karusic** | **org.kar.archidata** | **other** | | ||||
| | ----------------- | ------------------- | --------------------- | --------- | | ||||
| | `prod`            | INFO                | INFO                  | INFO      | | ||||
| | `prod-debug`      | DEBUG               | INFO                  | INFO      | | ||||
| @@ -89,4 +122,4 @@ export TAG_DOCKER=latest | ||||
| export REGISTRY_ADDRESS=gitea.atria-soft.org | ||||
| docker build -t ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karusic:${TAG_DOCKER} . | ||||
| docker push ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karusic:${TAG_DOCKER} | ||||
| ``` | ||||
| ``` | ||||
|   | ||||
| @@ -53,6 +53,9 @@ Checkstyle configuration that checks the sun coding conventions. | ||||
|     <module name="LambdaParameterName"/> | ||||
|     <module name="Regexp"/> | ||||
|     <module name="RegexpSinglelineJava"/> | ||||
|     <module name="UnusedPrivateField"> | ||||
|         <property name="ignorePattern" value="LOGGER"/> | ||||
|     </module> | ||||
|   </module> | ||||
|   <module name="BeforeExecutionExclusionFileFilter"> | ||||
|     <property name="fileNamePattern" value="module\-info\.java$"/> | ||||
|   | ||||
| @@ -18,5 +18,5 @@ WORKDIR /application/ | ||||
|  | ||||
| EXPOSE 18080 | ||||
|  | ||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karusic.WebLauncher"] | ||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.atriasoft.karusic.WebLauncher"] | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ mvn package | ||||
| // download all dependency in out/maven/dependency | ||||
| mvn dependency:copy-dependencies | ||||
|  | ||||
| java -cp out/maven/kar-karusic-0.1.0.jar  org.kar.karusic.WebLauncher | ||||
| java -cp out/maven/kar-karusic-0.1.0.jar  org.atriasoft.karusic.WebLauncher | ||||
|  | ||||
|  | ||||
| // create a single package jar | ||||
| @@ -19,7 +19,7 @@ mvn clean compile assembly:single | ||||
|  | ||||
|  | ||||
|  | ||||
| java -cp out/maven/karusic-0.1.0-jar-with-dependencies.jar org.kar.karusic.WebLauncher | ||||
| java -cp out/maven/karusic-0.1.0-jar-with-dependencies.jar org.atriasoft.karusic.WebLauncher | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										69
									
								
								back/pom.xml
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								back/pom.xml
									
									
									
									
									
								
							| @@ -1,26 +1,14 @@ | ||||
| <?xml version="1.0"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
| 	<modelVersion>4.0.0</modelVersion> | ||||
| 	<groupId>org.kar</groupId> | ||||
| 	<groupId>org.atriasoft</groupId> | ||||
| 	<artifactId>karusic</artifactId> | ||||
| 	<version>1.1.1-SNAPSHOT</version> | ||||
| 	<properties> | ||||
| 		<maven.compiler.version>3.13.0</maven.compiler.version> | ||||
| 		<maven.compiler.source>23</maven.compiler.source> | ||||
| 		<maven.compiler.target>23</maven.compiler.target> | ||||
| 		<maven.dependency.version>3.1.1</maven.dependency.version> | ||||
| 	</properties> | ||||
| 	<repositories> | ||||
| 		<repository> | ||||
| 			<id>gitea</id> | ||||
| 			<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> | ||||
| 		</repository> | ||||
| 	</repositories> | ||||
| 	<version>1.2.0</version> | ||||
| 	<dependencies> | ||||
| 		<dependency> | ||||
| 			<groupId>kangaroo-and-rabbit</groupId> | ||||
| 			<groupId>org.atria-soft</groupId> | ||||
| 			<artifactId>archidata</artifactId> | ||||
| 			<version>0.21.0</version> | ||||
| 			<version>0.30.4</version> | ||||
| 		</dependency> | ||||
| 		<!-- Loopback of logger JDK logging API to SLF4J --> | ||||
| 		<dependency> | ||||
| @@ -47,7 +35,7 @@ | ||||
| 		<dependency> | ||||
| 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||
| 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||
| 			<version>2.18.1</version> | ||||
| 			<version>2.18.3</version> | ||||
| 		</dependency> | ||||
| 		<!-- | ||||
| 		************************************************************  | ||||
| @@ -57,24 +45,24 @@ | ||||
| 		<dependency> | ||||
| 			<groupId>org.junit.jupiter</groupId> | ||||
| 			<artifactId>junit-jupiter-api</artifactId> | ||||
| 			<version>5.11.0</version> | ||||
| 			<version>5.12.1</version> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.junit.jupiter</groupId> | ||||
| 			<artifactId>junit-jupiter-engine</artifactId> | ||||
| 			<version>5.11.0</version> | ||||
| 			<version>5.12.1</version> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>net.revelc.code.formatter</groupId> | ||||
| 			<artifactId>formatter-maven-plugin</artifactId> | ||||
| 			<version>2.24.1</version> | ||||
| 			<version>2.25.0</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.apache.maven.plugins</groupId> | ||||
| 			<artifactId>maven-checkstyle-plugin</artifactId> | ||||
| 			<version>3.5.0</version> | ||||
| 			<version>3.6.0</version> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
| 	<build> | ||||
| @@ -95,18 +83,47 @@ | ||||
| 			<plugin> | ||||
| 				<groupId>org.apache.maven.plugins</groupId> | ||||
| 				<artifactId>maven-compiler-plugin</artifactId> | ||||
| 				<version>${maven.compiler.version}</version> | ||||
| 				<version>3.14.0</version> | ||||
| 				<configuration> | ||||
| 					<source>${maven.compiler.source}</source> | ||||
| 					<target>${maven.compiler.target}</target> | ||||
| 					<source>21</source> | ||||
| 					<target>21</target> | ||||
| 				</configuration> | ||||
| 			</plugin> | ||||
| 			<plugin> | ||||
| 				<groupId>org.codehaus.mojo</groupId> | ||||
| 				<artifactId>exec-maven-plugin</artifactId> | ||||
| 				<version>1.4.0</version> | ||||
| 				<version>3.2.0</version> | ||||
| 				<executions> | ||||
| 					<execution> | ||||
| 						<id>prod-mode</id> | ||||
| 						<goals> | ||||
| 							<goal>java</goal> | ||||
| 						</goals> | ||||
| 						<configuration> | ||||
| 							<mainClass>org.atriasoft.karusic.WebLauncher</mainClass> | ||||
| 						</configuration> | ||||
| 					</execution> | ||||
| 					<execution> | ||||
| 						<id>dev-mode</id> | ||||
| 						<goals> | ||||
| 							<goal>java</goal> | ||||
| 						</goals> | ||||
| 						<configuration> | ||||
| 							<mainClass>org.atriasoft.karusic.WebLauncherLocal</mainClass> | ||||
| 						</configuration> | ||||
| 					</execution> | ||||
| 					<execution> | ||||
| 						<id>generate-api</id> | ||||
| 						<goals> | ||||
| 							<goal>java</goal> | ||||
| 						</goals> | ||||
| 						<configuration> | ||||
| 							<mainClass>org.atriasoft.karusic.GenerateApi</mainClass> | ||||
| 						</configuration> | ||||
| 					</execution> | ||||
| 				</executions> | ||||
| 				<configuration> | ||||
| 					<mainClass>org.kar.karusic.WebLauncher</mainClass> | ||||
| 					<mainClass/> | ||||
| 				</configuration> | ||||
| 			</plugin> | ||||
| 			<!-- Create the source bundle --> | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| org.kar.karideo.dataTmpFolder=/application/data/tmp | ||||
| org.kar.karideo.dataTmpFolder=/application/data/media | ||||
| org.kar.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/ | ||||
| org.kar.karideo.db.host=1992.156.1.156 | ||||
| org.kar.karideo.db.port=20306 | ||||
| org.kar.karideo.db.login=root | ||||
| org.kar.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh | ||||
| org.kar.karideo.db.name=karideo | ||||
| org.kar.karideo.address=http://0.0.0.0:18080/karideo/api/ | ||||
| org.atriasoft.karideo.dataTmpFolder=/application/data/tmp | ||||
| org.atriasoft.karideo.dataTmpFolder=/application/data/media | ||||
| org.atriasoft.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/ | ||||
| org.atriasoft.karideo.db.host=1992.156.1.156 | ||||
| org.atriasoft.karideo.db.port=20306 | ||||
| org.atriasoft.karideo.db.login=root | ||||
| org.atriasoft.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh | ||||
| org.atriasoft.karideo.db.name=karideo | ||||
| org.atriasoft.karideo.address=http://0.0.0.0:18080/karideo/api/ | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.CodecBson; | ||||
| package org.atriasoft.karusic.CodecBson; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
							
								
								
									
										17
									
								
								back/src/org/atriasoft/karusic/GenerateApi.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								back/src/org/atriasoft/karusic/GenerateApi.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package org.atriasoft.karusic; | ||||
|  | ||||
| import org.atriasoft.karusic.migration.Initialization; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| public class GenerateApi { | ||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(GenerateApi.class); | ||||
|  | ||||
| 	private GenerateApi() {} | ||||
|  | ||||
| 	public static void main(final String[] args) throws Exception { | ||||
| 		LOGGER.info("Generate API"); | ||||
| 		Initialization.generateObjects(); | ||||
| 		LOGGER.info("STOP the REST server."); | ||||
| 	} | ||||
| } | ||||
| @@ -1,44 +1,42 @@ | ||||
| package org.kar.karusic; | ||||
| package org.atriasoft.karusic; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.Iterator; | ||||
| import java.util.TimeZone; | ||||
| import java.util.logging.LogManager; | ||||
| 
 | ||||
| import javax.imageio.ImageIO; | ||||
| import javax.imageio.ImageReader; | ||||
| import javax.imageio.ImageWriter; | ||||
| 
 | ||||
| import org.atriasoft.archidata.UpdateJwtPublicKey; | ||||
| import org.atriasoft.archidata.api.DataResource; | ||||
| import org.atriasoft.archidata.api.ProxyResource; | ||||
| import org.atriasoft.archidata.catcher.GenericCatcher; | ||||
| import org.atriasoft.archidata.db.DbConfig; | ||||
| import org.atriasoft.archidata.exception.DataAccessException; | ||||
| import org.atriasoft.archidata.filter.CORSFilter; | ||||
| import org.atriasoft.archidata.filter.OptionFilter; | ||||
| import org.atriasoft.archidata.migration.MigrationEngine; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.archidata.tools.ContextGenericTools; | ||||
| import org.atriasoft.karusic.api.AlbumResource; | ||||
| import org.atriasoft.karusic.api.ArtistResource; | ||||
| import org.atriasoft.karusic.api.Front; | ||||
| import org.atriasoft.karusic.api.GenderResource; | ||||
| import org.atriasoft.karusic.api.HealthCheck; | ||||
| import org.atriasoft.karusic.api.PlaylistResource; | ||||
| import org.atriasoft.karusic.api.TrackResource; | ||||
| import org.atriasoft.karusic.api.UserResource; | ||||
| import org.atriasoft.karusic.filter.KarusicAuthenticationFilter; | ||||
| import org.atriasoft.karusic.migration.Initialization; | ||||
| import org.atriasoft.karusic.migration.Migration20250427; | ||||
| import org.glassfish.grizzly.http.server.HttpServer; | ||||
| import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | ||||
| import org.glassfish.jersey.jackson.JacksonFeature; | ||||
| import org.glassfish.jersey.media.multipart.MultiPartFeature; | ||||
| import org.glassfish.jersey.server.ResourceConfig; | ||||
| import org.kar.archidata.UpdateJwtPublicKey; | ||||
| import org.kar.archidata.api.DataResource; | ||||
| import org.kar.archidata.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; | ||||
| import org.kar.karusic.api.GenderResource; | ||||
| import org.kar.karusic.api.HealthCheck; | ||||
| import org.kar.karusic.api.PlaylistResource; | ||||
| import org.kar.karusic.api.TrackResource; | ||||
| import org.kar.karusic.api.UserResource; | ||||
| import org.kar.karusic.filter.KarusicAuthenticationFilter; | ||||
| import org.kar.karusic.migration.Initialization; | ||||
| 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.glassfish.jersey.server.validation.ValidationFeature; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.slf4j.bridge.SLF4JBridgeHandler; | ||||
| @@ -51,6 +49,7 @@ public class WebLauncher { | ||||
| 	protected HttpServer server = null; | ||||
| 
 | ||||
| 	public WebLauncher() { | ||||
| 		TimeZone.setDefault(TimeZone.getTimeZone("UTC")); | ||||
| 		ConfigBaseVariable.bdDatabase = "karusic"; | ||||
| 	} | ||||
| 
 | ||||
| @@ -64,11 +63,7 @@ public class WebLauncher { | ||||
| 		WebLauncher.LOGGER.info("Add initialization"); | ||||
| 		migrationEngine.setInit(new Initialization()); | ||||
| 		WebLauncher.LOGGER.info("Add migration since last version"); | ||||
| 		migrationEngine.add(new Migration20231126()); | ||||
| 		migrationEngine.add(new Migration20240225()); | ||||
| 		migrationEngine.add(new Migration20240226()); | ||||
| 		migrationEngine.add(new Migration20240907()); | ||||
| 		migrationEngine.add(new Migration20250104()); | ||||
| 		migrationEngine.add(new Migration20250427()); | ||||
| 		WebLauncher.LOGGER.info("Migrate the DB [START]"); | ||||
| 		migrationEngine.migrateWaitAdmin(new DbConfig()); | ||||
| 		WebLauncher.LOGGER.info("Migrate the DB [STOP]"); | ||||
| @@ -151,6 +146,8 @@ public class WebLauncher { | ||||
| 
 | ||||
| 		// add jackson to be discover when we are ins standalone server | ||||
| 		rc.register(JacksonFeature.class); | ||||
| 		// enable jersey specific validations (@Valid) | ||||
| 		rc.register(ValidationFeature.class); | ||||
| 		// enable this to show low level request | ||||
| 		// rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); | ||||
| 
 | ||||
							
								
								
									
										52
									
								
								back/src/org/atriasoft/karusic/WebLauncherLocal.java
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										52
									
								
								back/src/org/atriasoft/karusic/WebLauncherLocal.java
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package org.atriasoft.karusic; | ||||
|  | ||||
| import java.util.logging.LogManager; | ||||
|  | ||||
| import org.atriasoft.archidata.exception.DataAccessException; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.karusic.migration.Initialization; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.slf4j.bridge.SLF4JBridgeHandler; | ||||
|  | ||||
| public class WebLauncherLocal extends WebLauncher { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | ||||
|  | ||||
| 	private WebLauncherLocal() {} | ||||
|  | ||||
| 	public static void main(final String[] args) throws Exception { | ||||
| 		// Loop-back of logger JDK logging API to SLF4J | ||||
| 		LogManager.getLogManager().reset(); | ||||
| 		SLF4JBridgeHandler.install(); | ||||
| 		// Generate the APIs in type-script | ||||
| 		Initialization.generateObjects(); | ||||
| 		final WebLauncherLocal launcher = new WebLauncherLocal(); | ||||
| 		launcher.process(); | ||||
| 		LOGGER.info("end-configure the server & wait finish process:"); | ||||
| 		Thread.currentThread().join(); | ||||
| 		LOGGER.info("STOP the REST server:"); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void process() throws InterruptedException, DataAccessException { | ||||
| 		if (true) { | ||||
| 			// for local test: | ||||
| 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; | ||||
| 			ConfigBaseVariable.testMode = "true"; | ||||
| 			ConfigBaseVariable.dbType = "mongo"; | ||||
| 		} | ||||
| 		// Test fail of SSO: ConfigBaseVariable.ssoAdress = null; | ||||
| 		try { | ||||
| 			super.migrateDB(); | ||||
| 		} catch (final Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			while (true) { | ||||
| 				LOGGER.error("============================================================================"); | ||||
| 				LOGGER.error("== Migration fail ==> waiting intervention of administrator..."); | ||||
| 				LOGGER.error("============================================================================"); | ||||
| 				Thread.sleep(60 * 60 * 1000); | ||||
| 			} | ||||
| 		} | ||||
| 		super.process(); | ||||
| 	} | ||||
| } | ||||
| @@ -1,31 +1,29 @@ | ||||
| package org.kar.karusic.api; | ||||
| package org.atriasoft.karusic.api; | ||||
| 
 | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||
| import org.atriasoft.archidata.tools.DataTools; | ||||
| import org.atriasoft.karusic.model.Album; | ||||
| 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.addOnSQL.AddOnDataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckFunction; | ||||
| import org.kar.archidata.tools.DataTools; | ||||
| import org.kar.karusic.model.Album; | ||||
| import org.kar.karusic.model.Album.AlbumChecker; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.validation.Valid; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.PATCH; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.PUT; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| @@ -35,14 +33,13 @@ import jakarta.ws.rs.core.MediaType; | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class AlbumResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(AlbumResource.class); | ||||
| 	static final AlbumChecker CHECKER = new AlbumChecker(); | ||||
| 
 | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	@Operation(description = "Get a specific Album with his ID") | ||||
| 	public Album get(@PathParam("id") final Long id) throws Exception { | ||||
| 		return DataAccess.get(Album.class, id); | ||||
| 	public Album get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		return DataAccess.get(Album.class, oid); | ||||
| 		// return this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).first(); | ||||
| 	} | ||||
| 
 | ||||
| @@ -59,30 +56,30 @@ public class AlbumResource { | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	@Operation(description = "Add an album (when all the data already exist)") | ||||
| 	public Album post(final Album data) throws Exception { | ||||
| 	public Album post(@Valid final Album data) throws Exception { | ||||
| 		// TODO: how to manage the checker ??? | ||||
| 		// final Album ret = this.morphiaService.getDatastore().save(data); | ||||
| 		// return ret; | ||||
| 		/* final MongoCollection<Track> 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)); | ||||
| 		return DataAccess.insert(data); | ||||
| 	} | ||||
| 
 | ||||
| 	@PATCH | ||||
| 	@Path("{id}") | ||||
| 	@PUT | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@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 { | ||||
| 	public Album put(@PathParam("oid") final ObjectId oid, @Valid final Album album) throws Exception { | ||||
| 		// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); | ||||
| 		// final UpdateOperations<Album> 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); | ||||
| 		album.oid = oid; | ||||
| 		DataAccess.update(album, oid); | ||||
| 		return DataAccess.get(Album.class, oid); | ||||
| 	} | ||||
| 
 | ||||
| 	// @PUT | ||||
| @@ -90,7 +87,7 @@ public class AlbumResource { | ||||
| 	// @RolesAllowed("ADMIN") | ||||
| 	// @Consumes(MediaType.APPLICATION_JSON) | ||||
| 	// @Operation(description = "Update a specific album") | ||||
| 	// public Album put(@PathParam("id") final Long id, final Album album) | ||||
| 	// public Album put(@PathParam("id") final ObjectId oid, final Album album) | ||||
| 	// throws Exception { | ||||
| 	// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)); | ||||
| 	// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class) | ||||
| @@ -100,11 +97,11 @@ public class AlbumResource { | ||||
| 	// } | ||||
| 
 | ||||
| 	@DELETE | ||||
| 	@Path("{id}") | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Operation(description = "Remove a specific album") | ||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||
| 		DataAccess.delete(Album.class, id); | ||||
| 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		DataAccess.delete(Album.class, oid); | ||||
| 		// this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).delete(); | ||||
| 	} | ||||
| 
 | ||||
| @@ -112,34 +109,34 @@ public class AlbumResource { | ||||
| 	 * @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 { | ||||
| 	 * @Operation(description = "Add a Track on a specific album") public Album addTrack(@PathParam("id") final ObjectId oid, @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") | ||||
| 	@Path("{oid}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@Operation(description = "Add a cover on a specific album") | ||||
| 	@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 { | ||||
| 	@ApiTypeScriptProgress | ||||
| 	public Album uploadCover(@PathParam("oid") final ObjectId oid, @ApiInputOptional @FormDataParam("uri") final String uri, @ApiInputOptional @FormDataParam("file") final InputStream fileInputStream, | ||||
| 			@ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			if (uri != null) { | ||||
| 				DataTools.uploadCoverFromUri(db, Album.class, id, uri); | ||||
| 				DataTools.uploadCoverFromUri(db, Album.class, oid, uri); | ||||
| 			} else { | ||||
| 				DataTools.uploadCover(db, Album.class, id, fileInputStream, fileMetaData); | ||||
| 				DataTools.uploadCover(db, Album.class, oid, fileInputStream, fileMetaData); | ||||
| 			} | ||||
| 			return db.get(Album.class, id); | ||||
| 			return db.get(Album.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@DELETE | ||||
| 	@Path("{id}/cover/{coverId}") | ||||
| 	@Path("{oid}/cover/{coverId}") | ||||
| 	@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 { | ||||
| 	public Album removeCover(@PathParam("oid") final ObjectId oid, @PathParam("coverId") final ObjectId coverId) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Album.class, "id", id, "covers", coverId); | ||||
| 			return db.get(Album.class, id); | ||||
| 			AddOnDataJson.removeLink(db, Album.class, "id", oid, "covers", coverId); | ||||
| 			return db.get(Album.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										99
									
								
								back/src/org/atriasoft/karusic/api/ArtistResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								back/src/org/atriasoft/karusic/api/ArtistResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| package org.atriasoft.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||
| import org.atriasoft.archidata.tools.DataTools; | ||||
| import org.atriasoft.karusic.model.Artist; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.validation.Valid; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.PUT; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/artist") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class ArtistResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(ArtistResource.class); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Artist get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		return DataAccess.get(Artist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Artist> gets() throws Exception { | ||||
| 		return DataAccess.gets(Artist.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Artist post(@Valid final Artist data) throws Exception { | ||||
| 		return DataAccess.insert(data); | ||||
| 	} | ||||
|  | ||||
| 	@PUT | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Artist put(@PathParam("oid") final ObjectId oid, @Valid final Artist artist) throws Exception { | ||||
| 		artist.oid = oid; | ||||
| 		DataAccess.update(artist, oid); | ||||
| 		return DataAccess.get(Artist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		DataAccess.delete(Artist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{oid}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@ApiTypeScriptProgress | ||||
| 	public Artist uploadCover(@PathParam("oid") final ObjectId oid, @ApiInputOptional @FormDataParam("uri") final String uri, | ||||
| 			@ApiInputOptional @FormDataParam("file") final InputStream fileInputStream, @ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			if (uri != null) { | ||||
| 				DataTools.uploadCoverFromUri(db, Artist.class, oid, uri); | ||||
| 			} else { | ||||
| 				DataTools.uploadCover(db, Artist.class, oid, fileInputStream, fileMetaData); | ||||
| 			} | ||||
| 			return db.get(Artist.class, oid); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public Artist removeCover(@PathParam("oid") final ObjectId oid, @PathParam("coverId") final ObjectId coverId) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Artist.class, "id", oid, "covers", coverId); | ||||
| 			return db.get(Artist.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| package org.kar.karusic.api; | ||||
| package org.atriasoft.karusic.api; | ||||
| 
 | ||||
| import org.kar.archidata.api.FrontGeneric; | ||||
| import org.kar.karusic.util.ConfigVariable; | ||||
| import org.atriasoft.archidata.api.FrontGeneric; | ||||
| import org.atriasoft.karusic.util.ConfigVariable; | ||||
| 
 | ||||
| import jakarta.ws.rs.Path; | ||||
| 
 | ||||
							
								
								
									
										99
									
								
								back/src/org/atriasoft/karusic/api/GenderResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								back/src/org/atriasoft/karusic/api/GenderResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| package org.atriasoft.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||
| import org.atriasoft.archidata.tools.DataTools; | ||||
| import org.atriasoft.karusic.model.Gender; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.validation.Valid; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.PUT; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/gender") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class GenderResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(GenderResource.class); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Gender get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		return DataAccess.get(Gender.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Gender> gets() throws Exception { | ||||
| 		return DataAccess.gets(Gender.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Gender post(@Valid final Gender data) throws Exception { | ||||
| 		return DataAccess.insert(data); | ||||
| 	} | ||||
|  | ||||
| 	@PUT | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Gender patch(@PathParam("oid") final ObjectId oid, @Valid final Gender gender) throws Exception { | ||||
| 		gender.oid = oid; | ||||
| 		DataAccess.update(gender, oid); | ||||
| 		return DataAccess.get(Gender.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		DataAccess.delete(Gender.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{oid}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@ApiTypeScriptProgress | ||||
| 	public Gender uploadCover(@PathParam("oid") final ObjectId oid, @ApiInputOptional @FormDataParam("uri") final String uri, | ||||
| 			@ApiInputOptional @FormDataParam("file") final InputStream fileInputStream, @ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			if (uri != null) { | ||||
| 				DataTools.uploadCoverFromUri(db, Gender.class, oid, uri); | ||||
| 			} else { | ||||
| 				DataTools.uploadCover(db, Gender.class, oid, fileInputStream, fileMetaData); | ||||
| 			} | ||||
| 			return db.get(Gender.class, oid); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public Gender removeCover(@PathParam("oid") final ObjectId oid, @PathParam("coverId") final ObjectId coverId) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Gender.class, "_id", oid, "covers", coverId); | ||||
| 			return db.get(Gender.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,8 +1,8 @@ | ||||
| package org.kar.karusic.api; | ||||
| package org.atriasoft.karusic.api; | ||||
| 
 | ||||
| import org.kar.archidata.exception.FailException; | ||||
| import org.kar.archidata.tools.ConfigBaseVariable; | ||||
| import org.kar.archidata.tools.JWTWrapper; | ||||
| import org.atriasoft.archidata.exception.FailException; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.archidata.tools.JWTWrapper; | ||||
| 
 | ||||
| import jakarta.annotation.security.PermitAll; | ||||
| import jakarta.ws.rs.GET; | ||||
							
								
								
									
										93
									
								
								back/src/org/atriasoft/karusic/api/PlaylistResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								back/src/org/atriasoft/karusic/api/PlaylistResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| package org.atriasoft.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAsyncType; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||
| import org.atriasoft.archidata.tools.DataTools; | ||||
| import org.atriasoft.karusic.model.Playlist; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.validation.Valid; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.PUT; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/playlist") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class PlaylistResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistResource.class); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Playlist get(@PathParam("id") final ObjectId oid) throws Exception { | ||||
| 		return DataAccess.get(Playlist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Playlist> gets() throws Exception { | ||||
| 		return DataAccess.gets(Playlist.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Playlist post(@Valid final Playlist data) throws Exception { | ||||
| 		return DataAccess.insert(data); | ||||
| 	} | ||||
|  | ||||
| 	@PUT | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Playlist put(@PathParam("oid") final ObjectId oid, @Valid final Playlist playlist) throws Exception { | ||||
| 		playlist.oid = oid; | ||||
| 		DataAccess.update(playlist, oid); | ||||
| 		return DataAccess.get(Playlist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		DataAccess.delete(Playlist.class, oid); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{oid}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@ApiAsyncType(Playlist.class) | ||||
| 	public void uploadCover(@PathParam("oid") final ObjectId oid, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) | ||||
| 			throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			DataTools.uploadCover(db, Playlist.class, oid, fileInputStream, fileMetaData); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{oid}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public Playlist removeCover(@PathParam("oid") final ObjectId oid, @PathParam("coverId") final ObjectId coverId) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Playlist.class, "id", oid, "covers", coverId); | ||||
| 			return DataAccess.get(Playlist.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.api; | ||||
| package org.atriasoft.karusic.api; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| @@ -6,29 +6,28 @@ import java.sql.SQLException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAsyncType; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.tools.DataTools; | ||||
| import org.atriasoft.karusic.model.Track; | ||||
| 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.addOnSQL.AddOnDataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckFunction; | ||||
| import org.kar.archidata.model.Data; | ||||
| import org.kar.archidata.tools.DataTools; | ||||
| import org.kar.karusic.model.Track; | ||||
| import org.kar.karusic.model.Track.TrackChecker; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.validation.Valid; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.PATCH; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.PUT; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| @@ -39,13 +38,12 @@ import jakarta.ws.rs.core.Response; | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class TrackResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(TrackResource.class); | ||||
| 	static final TrackChecker CHECKER = new TrackChecker(); | ||||
| 
 | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Track get(@PathParam("id") final Long id) throws Exception { | ||||
| 		return DataAccess.get(Track.class, id); | ||||
| 	public Track get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		return DataAccess.get(Track.class, oid); | ||||
| 	} | ||||
| 
 | ||||
| 	@GET | ||||
| @@ -57,71 +55,51 @@ public class TrackResource { | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Track post(final Track data) throws Exception { | ||||
| 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||
| 	public Track post(@Valid final Track data) throws Exception { | ||||
| 		return DataAccess.insert(data); | ||||
| 	} | ||||
| 
 | ||||
| 	@PATCH | ||||
| 	@Path("{id}") | ||||
| 	@PUT | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Track patch(@PathParam("id") final Long id, @AsyncType(Track.class) final String jsonRequest) throws Exception { | ||||
| 		DataAccess.updateWithJson(Track.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||
| 		return DataAccess.get(Track.class, id); | ||||
| 	public Track put(@PathParam("oid") final ObjectId oid, @Valid final Track track) throws Exception { | ||||
| 		track.oid = oid; | ||||
| 		DataAccess.update(track, oid); | ||||
| 		return DataAccess.get(Track.class, oid); | ||||
| 	} | ||||
| 
 | ||||
| 	@DELETE | ||||
| 	@Path("{id}") | ||||
| 	@Path("{oid}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||
| 		DataAccess.delete(Track.class, id); | ||||
| 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||
| 		DataAccess.delete(Track.class, oid); | ||||
| 	} | ||||
| 
 | ||||
| 	@POST | ||||
| 	@Path("{id}/artist/{artistId}") | ||||
| 	@Path("{oid}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { | ||||
| 		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 { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId); | ||||
| 			return DataAccess.get(Track.class, id); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@POST | ||||
| 	@Path("{id}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@TypeScriptProgress | ||||
| 	public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream, | ||||
| 	@ApiTypeScriptProgress | ||||
| 	public Track uploadCover(@PathParam("oid") final ObjectId oid, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream, | ||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			if (uri != null) { | ||||
| 				DataTools.uploadCoverFromUri(db, Track.class, id, uri); | ||||
| 				DataTools.uploadCoverFromUri(db, Track.class, oid, uri); | ||||
| 			} else { | ||||
| 				DataTools.uploadCover(db, Track.class, id, fileInputStream, fileMetaData); | ||||
| 				DataTools.uploadCover(db, Track.class, oid, fileInputStream, fileMetaData); | ||||
| 			} | ||||
| 			return DataAccess.get(Track.class, id); | ||||
| 			return DataAccess.get(Track.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@DELETE | ||||
| 	@Path("{id}/cover/{coverId}") | ||||
| 	@Path("{oid}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception { | ||||
| 	public Track removeCover(@PathParam("oid") final ObjectId oid, @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); | ||||
| 			AddOnDataJson.removeLink(db, Track.class, "_id", oid, "covers", coverId); | ||||
| 			return db.get(Track.class, oid); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @@ -129,14 +107,14 @@ public class TrackResource { | ||||
| 	@Path("upload/") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@AsyncType(Track.class) | ||||
| 	@TypeScriptProgress | ||||
| 	@ApiAsyncType(Track.class) | ||||
| 	@ApiTypeScriptProgress | ||||
| 	public Response uploadTrack( // | ||||
| 			@FormDataParam("title") String title, // | ||||
| 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("genderId") String genderId, // | ||||
| 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("artistId") String artistId, // | ||||
| 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("albumId") String albumId, // | ||||
| 			@FormDataOptional @AsyncType(Long.class) @FormDataParam("trackId") String trackId, // | ||||
| 			@ApiInputOptional @ApiAsyncType(ObjectId.class) @FormDataParam("genderId") String genderId, // | ||||
| 			@ApiInputOptional @ApiAsyncType(ObjectId.class) @FormDataParam("artistId") String artistId, // | ||||
| 			@ApiInputOptional @ApiAsyncType(ObjectId.class) @FormDataParam("albumId") String albumId, // | ||||
| 			@ApiInputOptional @ApiAsyncType(Long.class) @FormDataParam("trackId") String trackId, // | ||||
| 			@FormDataParam("file") final InputStream fileInputStream, // | ||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData // | ||||
| 	) { | ||||
| @@ -157,7 +135,7 @@ public class TrackResource { | ||||
| 			LOGGER.info("    > title: " + title); | ||||
| 			LOGGER.info("    > fileInputStream: " + fileInputStream); | ||||
| 			LOGGER.info("    > fileMetaData: " + fileMetaData); | ||||
| 			/* if (typeId == null) { return Response.status(406). entity("Missong Input 'type'"). type("text/plain"). build(); } */ | ||||
| 			/* if (typeId == null) { return Response.status(406). entity("Missing Input 'type'"). type("text/plain"). build(); } */ | ||||
| 
 | ||||
| 			final long tmpUID = DataTools.getTmpDataId(); | ||||
| 			final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID); | ||||
| @@ -188,15 +166,17 @@ public class TrackResource { | ||||
| 			Track trackElem = new Track(); | ||||
| 			trackElem.name = title; | ||||
| 			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.albumId = albumId != null ? new ObjectId(albumId) : null; | ||||
| 			trackElem.genderId = genderId != null ? new ObjectId(genderId) : null; | ||||
| 			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.artists.add(artistId != null ? new ObjectId(artistId) : null); | ||||
| 			} | ||||
| 			trackElem = DataAccess.insert(trackElem, new CheckFunction(CHECKER)); | ||||
| 			// TODO: maybe validate here .... | ||||
| 
 | ||||
| 			trackElem = DataAccess.insert(trackElem); | ||||
| 			/* 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) { | ||||
| @@ -1,13 +1,13 @@ | ||||
| package org.kar.karusic.api; | ||||
| package org.atriasoft.karusic.api; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.kar.archidata.dataAccess.DataAccess; | ||||
| import org.kar.archidata.filter.GenericContext; | ||||
| import org.kar.karusic.api.UserResourceModel.PartRight; | ||||
| import org.kar.karusic.api.UserResourceModel.UserMe; | ||||
| import org.kar.karusic.model.UserKarusic; | ||||
| import org.atriasoft.archidata.dataAccess.DataAccess; | ||||
| import org.atriasoft.archidata.filter.GenericContext; | ||||
| import org.atriasoft.karusic.api.UserResourceModel.PartRight; | ||||
| import org.atriasoft.karusic.api.UserResourceModel.UserMe; | ||||
| import org.atriasoft.karusic.model.UserKarusic; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @@ -1,10 +1,7 @@ | ||||
| package org.kar.karusic.api.UserResourceModel; | ||||
| package org.atriasoft.karusic.api.UserResourceModel; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| 
 | ||||
| import org.kar.archidata.annotation.NoWriteSpecificMode; | ||||
| 
 | ||||
| @NoWriteSpecificMode | ||||
| public class ModuleAuthorizations extends HashMap<String, PartRight> { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.api.UserResourceModel; | ||||
| package org.atriasoft.karusic.api.UserResourceModel; | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonValue; | ||||
| 
 | ||||
| @@ -1,12 +1,9 @@ | ||||
| package org.kar.karusic.api.UserResourceModel; | ||||
| package org.atriasoft.karusic.api.UserResourceModel; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.kar.archidata.annotation.NoWriteSpecificMode; | ||||
| 
 | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| 
 | ||||
| @NoWriteSpecificMode | ||||
| public class UserMe { | ||||
| 	public long id; | ||||
| 	public String login; | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.kar.karusic.filter; | ||||
| package org.atriasoft.karusic.filter; | ||||
| 
 | ||||
| import org.kar.archidata.filter.AuthenticationFilter; | ||||
| import org.atriasoft.archidata.filter.AuthenticationFilter; | ||||
| 
 | ||||
| import jakarta.ws.rs.Priorities; | ||||
| import jakarta.ws.rs.ext.Provider; | ||||
							
								
								
									
										112
									
								
								back/src/org/atriasoft/karusic/migration/Initialization.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								back/src/org/atriasoft/karusic/migration/Initialization.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| package org.atriasoft.karusic.migration; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.api.DataResource; | ||||
| import org.atriasoft.archidata.api.ProxyResource; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.externalRestApi.AnalyzeApi; | ||||
| import org.atriasoft.archidata.externalRestApi.TsGenerateApi; | ||||
| import org.atriasoft.archidata.filter.PartRight; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.User; | ||||
| import org.atriasoft.archidata.model.token.JwtToken; | ||||
| import org.atriasoft.karusic.api.AlbumResource; | ||||
| import org.atriasoft.karusic.api.ArtistResource; | ||||
| import org.atriasoft.karusic.api.Front; | ||||
| import org.atriasoft.karusic.api.GenderResource; | ||||
| import org.atriasoft.karusic.api.HealthCheck; | ||||
| import org.atriasoft.karusic.api.PlaylistResource; | ||||
| import org.atriasoft.karusic.api.TrackResource; | ||||
| import org.atriasoft.karusic.api.UserResource; | ||||
| import org.atriasoft.karusic.model.Album; | ||||
| import org.atriasoft.karusic.model.Artist; | ||||
| import org.atriasoft.karusic.model.Gender; | ||||
| import org.atriasoft.karusic.model.Playlist; | ||||
| import org.atriasoft.karusic.model.Track; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| public class Initialization extends MigrationSqlStep { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class); | ||||
|  | ||||
| 	public static final int KARSO_INITIALISATION_ID = 1; | ||||
| 	public static final List<Class<?>> CLASSES_BASE = List.of(Album.class, Artist.class, Data.class, Gender.class, Playlist.class, Track.class, User.class); | ||||
|  | ||||
| 	@Override | ||||
| 	public String getName() { | ||||
| 		return "Initialization"; | ||||
| 	} | ||||
|  | ||||
| 	public static void generateObjects() throws Exception { | ||||
| 		LOGGER.info("Generate APIs"); | ||||
| 		final List<Class<?>> listOfResources = List.of(AlbumResource.class, ArtistResource.class, Front.class, GenderResource.class, HealthCheck.class, PlaylistResource.class, UserResource.class, | ||||
| 				TrackResource.class, DataResource.class, ProxyResource.class); | ||||
| 		final AnalyzeApi api = new AnalyzeApi(); | ||||
| 		api.addAllApi(listOfResources); | ||||
| 		api.addModel(JwtToken.class); | ||||
| 		api.addModel(PartRight.class); | ||||
| 		TsGenerateApi.generateApi(api, "../front/src/back-api/"); | ||||
| 		LOGGER.info("Generate APIs (DONE)"); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void generateStep() throws Exception { | ||||
| 		for (final Class<?> clazz : CLASSES_BASE) { | ||||
| 			addClass(clazz); | ||||
| 		} | ||||
| 		addAction((final DBAccess da) -> { | ||||
| 			final List<Gender> data = List.of(// | ||||
| 					new Gender("Variété française"), // | ||||
| 					new Gender("Pop"), // | ||||
| 					new Gender("inconnue"), // | ||||
| 					new Gender("Disco"), // | ||||
| 					new Gender("Enfants"), // | ||||
| 					new Gender("Portugaise"), // | ||||
| 					new Gender("Apprentissage"), // | ||||
| 					new Gender("Blues"), // | ||||
| 					new Gender("Jazz"), // | ||||
| 					new Gender("Chanson Noël"), // | ||||
| 					new Gender("DubStep"), // | ||||
| 					new Gender("Rap français"), // | ||||
| 					new Gender("Classique"), // | ||||
| 					new Gender("Rock"), // | ||||
| 					new Gender("Electro"), // | ||||
| 					new Gender("Celtique"), // | ||||
| 					new Gender("Country"), // | ||||
| 					new Gender("Variété Québéquoise"), // | ||||
| 					new Gender("Médiéval"), // | ||||
| 					new Gender("Variété Italienne"), // | ||||
| 					new Gender("Comédie Musicale"), // | ||||
| 					new Gender("Vianney"), // | ||||
| 					new Gender("Bande Original"), // | ||||
| 					new Gender("Bande Originale"), // | ||||
| 					new Gender("Variété Belge"), // | ||||
| 					new Gender("Gospel")); | ||||
| 			da.insertMultiple(data); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	public static void dropAll(final DBAccess da) { | ||||
| 		for (final Class<?> element : CLASSES_BASE) { | ||||
| 			try { | ||||
| 				da.drop(element); | ||||
| 			} catch (final Exception ex) { | ||||
| 				LOGGER.error("Fail to drop table !!!!!!"); | ||||
| 				ex.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static void cleanAll(final DBAccess da) { | ||||
| 		for (final Class<?> element : CLASSES_BASE) { | ||||
| 			try { | ||||
| 				da.cleanAll(element); | ||||
| 			} catch (final Exception ex) { | ||||
| 				LOGGER.error("Fail to clean table !!!!!!"); | ||||
| 				ex.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.kar.karusic.migration; | ||||
| package org.atriasoft.karusic.migration; | ||||
| 
 | ||||
| import org.kar.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| 
 | ||||
| public class Migration20231126 extends MigrationSqlStep { | ||||
| 
 | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.kar.karusic.migration; | ||||
| package org.atriasoft.karusic.migration; | ||||
| 
 | ||||
| import org.kar.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| 
 | ||||
| public class Migration20240225 extends MigrationSqlStep { | ||||
| 
 | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.kar.karusic.migration; | ||||
| package org.atriasoft.karusic.migration; | ||||
| 
 | ||||
| import org.kar.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.kar.karusic.migration; | ||||
| package org.atriasoft.karusic.migration; | ||||
| 
 | ||||
| import org.kar.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.migration; | ||||
| package org.atriasoft.karusic.migration; | ||||
| 
 | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.NoSuchFileException; | ||||
| @@ -9,14 +9,14 @@ 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.atriasoft.archidata.api.DataResource; | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems; | ||||
| import org.atriasoft.archidata.dataAccess.options.OverrideTableName; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.karusic.migration.model.CoverConversion; | ||||
| import org.atriasoft.karusic.migration.model.MediaConversion; | ||||
| import org.atriasoft.karusic.migration.model.OIDConversion; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @@ -0,0 +1,30 @@ | ||||
| package org.atriasoft.karusic.migration; | ||||
|  | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| public class Migration20250414 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-04-14: update constraints"; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void generateStep() throws Exception { | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `artist` | ||||
| 				CHANGE `birth` `birth` timestamp(3) NULL AFTER `surname`, | ||||
| 				CHANGE `death` `death` timestamp(3) NULL AFTER `birth`; | ||||
| 				"""); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `album` | ||||
| 				CHANGE `publication` `publication` timestamp(3) NULL AFTER `description`; | ||||
| 				"""); | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										148
									
								
								back/src/org/atriasoft/karusic/migration/Migration20250427.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								back/src/org/atriasoft/karusic/migration/Migration20250427.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| package org.atriasoft.karusic.migration; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems; | ||||
| import org.atriasoft.archidata.dataAccess.options.DirectData; | ||||
| import org.atriasoft.archidata.dataAccess.options.ReadAllColumn; | ||||
| import org.atriasoft.archidata.db.DbConfig; | ||||
| import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.karusic.model.Album; | ||||
| import org.atriasoft.karusic.model.Artist; | ||||
| import org.atriasoft.karusic.model.Gender; | ||||
| import org.atriasoft.karusic.model.Track; | ||||
| import org.atriasoft.karusic.modelOld.AlbumOld; | ||||
| import org.atriasoft.karusic.modelOld.ArtistOld; | ||||
| import org.atriasoft.karusic.modelOld.GenderOld; | ||||
| import org.atriasoft.karusic.modelOld.TrackOld; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| public class Migration20250427 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-04-27: Migrate to MongoDB"; | ||||
| 	} | ||||
|  | ||||
| 	public static ObjectId getElementArtist(final List<ArtistOld> datas, final Long id) throws Exception { | ||||
| 		if (id == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		for (final var elem : datas) { | ||||
| 			if (elem.id.equals(id)) { | ||||
| 				return elem.getOid(); | ||||
| 			} | ||||
| 		} | ||||
| 		throw new Exception("Does not exist"); | ||||
| 	} | ||||
|  | ||||
| 	public static ObjectId getElementAlbum(final List<AlbumOld> datas, final Long id) throws Exception { | ||||
| 		if (id == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		for (final var elem : datas) { | ||||
| 			if (elem.id.equals(id)) { | ||||
| 				return elem.getOid(); | ||||
| 			} | ||||
| 		} | ||||
| 		throw new Exception("Does not exist"); | ||||
| 	} | ||||
|  | ||||
| 	public static ObjectId getElementGender(final List<GenderOld> datas, final Long id) throws Exception { | ||||
| 		if (id == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		for (final var elem : datas) { | ||||
| 			if (elem.id.equals(id)) { | ||||
| 				return elem.getOid(); | ||||
| 			} | ||||
| 		} | ||||
| 		throw new Exception("Does not exist"); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void generateStep() throws Exception { | ||||
| 		addAction((final DBAccess daMongo) -> { | ||||
| 			// Create the previous connection on SQL: | ||||
| 			final DbConfig configSQL = new DbConfig("mysql", ConfigBaseVariable.getDBHost(), (short) 3906, | ||||
| 					// final DbConfig config = new DbConfig("mysql", "db", (short) 3306, | ||||
| 					ConfigBaseVariable.getDBLogin(), ConfigBaseVariable.getDBPassword(), ConfigBaseVariable.getDBName(), ConfigBaseVariable.getDBKeepConnected(), | ||||
| 					List.of(ConfigBaseVariable.getBbInterfacesClasses())); | ||||
| 			try (final DBAccess daSQL = DBAccess.createInterface(configSQL)) { | ||||
| 				final List<Data> allData = daSQL.gets(Data.class, new ReadAllColumn(), new AccessDeletedItems()); | ||||
| 				final List<AlbumOld> allOldAlbums = daSQL.gets(AlbumOld.class, new ReadAllColumn(), new AccessDeletedItems()); | ||||
| 				final List<ArtistOld> allOldArtist = daSQL.gets(ArtistOld.class, new ReadAllColumn(), new AccessDeletedItems()); | ||||
| 				final List<GenderOld> allOldGender = daSQL.gets(GenderOld.class, new ReadAllColumn(), new AccessDeletedItems()); | ||||
| 				final List<TrackOld> allTOldrack = daSQL.gets(TrackOld.class, new ReadAllColumn(), new AccessDeletedItems()); | ||||
| 				for (final Data elem : allData) { | ||||
| 					daMongo.insert(elem, new DirectData()); | ||||
| 				} | ||||
| 				for (final AlbumOld elem : allOldAlbums) { | ||||
| 					final Album tmp = new Album(); | ||||
| 					tmp.oid = elem.getOid(); | ||||
| 					tmp.deleted = elem.deleted; | ||||
| 					tmp.updatedAt = elem.updatedAt; | ||||
| 					tmp.createdAt = elem.createdAt; | ||||
| 					tmp.name = elem.name; | ||||
| 					tmp.description = elem.description; | ||||
| 					tmp.covers = elem.covers; | ||||
| 					daMongo.insert(tmp, new DirectData()); | ||||
| 				} | ||||
| 				for (final ArtistOld elem : allOldArtist) { | ||||
| 					final Artist tmp = new Artist(); | ||||
| 					tmp.oid = elem.getOid(); | ||||
| 					tmp.deleted = elem.deleted; | ||||
| 					tmp.updatedAt = elem.updatedAt; | ||||
| 					tmp.createdAt = elem.createdAt; | ||||
| 					tmp.name = elem.name; | ||||
| 					tmp.description = elem.description; | ||||
| 					tmp.covers = elem.covers; | ||||
| 					tmp.firstName = elem.firstName; | ||||
| 					tmp.birth = elem.birth; | ||||
| 					tmp.death = elem.death; | ||||
| 					daMongo.insert(tmp, new DirectData()); | ||||
| 				} | ||||
| 				for (final GenderOld elem : allOldGender) { | ||||
| 					final Gender tmp = new Gender(); | ||||
| 					tmp.oid = elem.getOid(); | ||||
| 					tmp.deleted = elem.deleted; | ||||
| 					tmp.updatedAt = elem.updatedAt; | ||||
| 					tmp.createdAt = elem.createdAt; | ||||
| 					tmp.name = elem.name; | ||||
| 					tmp.description = elem.description; | ||||
| 					tmp.covers = elem.covers; | ||||
| 					daMongo.insert(tmp, new DirectData()); | ||||
| 				} | ||||
| 				for (final TrackOld elem : allTOldrack) { | ||||
| 					final Track tmp = new Track(); | ||||
| 					tmp.oid = elem.getOid(); | ||||
| 					tmp.deleted = elem.deleted; | ||||
| 					tmp.updatedAt = elem.updatedAt; | ||||
| 					tmp.createdAt = elem.createdAt; | ||||
| 					tmp.name = elem.name; | ||||
| 					tmp.description = elem.description; | ||||
| 					tmp.covers = elem.covers; | ||||
| 					tmp.genderId = getElementGender(allOldGender, elem.genderId); | ||||
| 					tmp.albumId = getElementAlbum(allOldAlbums, elem.albumId); | ||||
| 					tmp.track = elem.track; | ||||
| 					tmp.dataId = elem.dataId; | ||||
| 					tmp.artists = new ArrayList<>(); | ||||
| 					for (final Long artistId : elem.artists) { | ||||
| 						tmp.artists.add(getElementArtist(allOldArtist, artistId)); | ||||
| 					} | ||||
| 					daMongo.insert(tmp, new DirectData()); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,10 +1,10 @@ | ||||
| package org.kar.karusic.migration.model; | ||||
| package org.atriasoft.karusic.migration.model; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.atriasoft.archidata.annotation.DataJson; | ||||
| 
 | ||||
| import jakarta.persistence.Id; | ||||
| 
 | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.migration.model; | ||||
| package org.atriasoft.karusic.migration.model; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.migration.model; | ||||
| package org.atriasoft.karusic.migration.model; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
							
								
								
									
										44
									
								
								back/src/org/atriasoft/karusic/model/Album.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								back/src/org/atriasoft/karusic/model/Album.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package org.atriasoft.karusic.model; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.hibernate.validator.constraints.UniqueElements; | ||||
|  | ||||
| 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.validation.constraints.NotNull; | ||||
| import jakarta.validation.constraints.Size; | ||||
|  | ||||
| @Entity() | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| @ApiGenerationMode(create = true, update = true) | ||||
| public class Album extends OIDGenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	@Size(min = 0, max = 8192) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@Nullable | ||||
| 	@CollectionNotEmpty | ||||
| 	@UniqueElements | ||||
| 	@ApiAccessLimitation(readable = true, creatable = false, updatable = false) | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
|  | ||||
| 	public Date publication; | ||||
| } | ||||
							
								
								
									
										56
									
								
								back/src/org/atriasoft/karusic/model/Artist.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								back/src/org/atriasoft/karusic/model/Artist.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| package org.atriasoft.karusic.model; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.hibernate.validator.constraints.UniqueElements; | ||||
|  | ||||
| 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.validation.constraints.NotNull; | ||||
| import jakarta.validation.constraints.Size; | ||||
|  | ||||
| @Entity() | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| @ApiGenerationMode(create = true, update = true) | ||||
| public class Artist extends OIDGenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	@Size(min = 0, max = 8192) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@Nullable | ||||
| 	@CollectionNotEmpty | ||||
| 	@UniqueElements | ||||
| 	@ApiAccessLimitation(readable = true, creatable = false, updatable = false) | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String firstName = null; | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String surname = null; | ||||
| 	public Date birth = null; | ||||
| 	public Date death = null; | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return "Artist [id=" + this.oid + ", name=" + this.name + ", description=" + this.description + ", covers=" + this.covers + ", firstName=" + this.firstName + ", surname=" + this.surname | ||||
| 				+ ", birth=" + this.birth + ", death=" + this.death + "]"; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										65
									
								
								back/src/org/atriasoft/karusic/model/Gender.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								back/src/org/atriasoft/karusic/model/Gender.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| package org.atriasoft.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
| */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.hibernate.validator.constraints.UniqueElements; | ||||
|  | ||||
| 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.validation.constraints.NotNull; | ||||
| import jakarta.validation.constraints.Size; | ||||
|  | ||||
| @Entity() | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| @ApiGenerationMode(create = true, update = true) | ||||
| public class Gender extends OIDGenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	@Size(min = 0, max = 8192) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@Nullable | ||||
| 	@CollectionNotEmpty | ||||
| 	@UniqueElements | ||||
| 	@ApiAccessLimitation(readable = true, creatable = false, updatable = false) | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
|  | ||||
| 	public Gender() {} | ||||
|  | ||||
| 	public Gender(final String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	public Gender(final ObjectId oid, final String name) { | ||||
| 		this.oid = oid; | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										54
									
								
								back/src/org/atriasoft/karusic/model/Playlist.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								back/src/org/atriasoft/karusic/model/Playlist.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| package org.atriasoft.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
| */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.hibernate.validator.constraints.UniqueElements; | ||||
|  | ||||
| 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.validation.constraints.NotNull; | ||||
| import jakarta.validation.constraints.Size; | ||||
|  | ||||
| @Entity() | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| @ApiGenerationMode(create = true, update = true) | ||||
| public class Playlist extends OIDGenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	@Size(min = 0, max = 8192) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@Nullable | ||||
| 	@CollectionNotEmpty | ||||
| 	@UniqueElements | ||||
| 	@ApiAccessLimitation(readable = true, creatable = false, updatable = false) | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
| 	public List<@CheckForeignKey(target = Track.class) @NotNull ObjectId> tracks = null; | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.model; | ||||
| package org.atriasoft.karusic.model; | ||||
| 
 | ||||
| public enum State { | ||||
| 	// User has remove his account | ||||
							
								
								
									
										71
									
								
								back/src/org/atriasoft/karusic/model/Track.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								back/src/org/atriasoft/karusic/model/Track.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| package org.atriasoft.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
|  */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiAccessLimitation; | ||||
| import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
| import org.hibernate.validator.constraints.UniqueElements; | ||||
|  | ||||
| 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.validation.constraints.NotNull; | ||||
| import jakarta.validation.constraints.PositiveOrZero; | ||||
| import jakarta.validation.constraints.Size; | ||||
|  | ||||
| @Entity() | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| @ApiGenerationMode(create = true, update = true) | ||||
| public class Track extends OIDGenericDataSoftDelete { | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	@Size(min = 1, max = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	@Size(min = 0, max = 8192) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@Nullable | ||||
| 	@CollectionNotEmpty | ||||
| 	@UniqueElements | ||||
| 	@ApiAccessLimitation(readable = true, creatable = false, updatable = false) | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
| 	@CheckForeignKey(target = Gender.class) | ||||
| 	public ObjectId genderId = null; | ||||
| 	@CheckForeignKey(target = Album.class) | ||||
| 	public ObjectId albumId = null; | ||||
| 	@PositiveOrZero | ||||
| 	public Long track = null; | ||||
| 	@CheckForeignKey(target = Data.class) | ||||
| 	public ObjectId dataId = null; | ||||
| 	@Column(length = 0) | ||||
| 	public List<@CheckForeignKey(target = Artist.class) @NotNull ObjectId> artists = null; | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return "Track [oid=" + this.oid + ", deleted=" + this.deleted + ", createdAt=" + this.createdAt + ", updatedAt=" + this.updatedAt + ", name=" + this.name + ", description=" + this.description | ||||
| 				+ ", covers=" + this.covers + ", genderId=" + this.genderId + ", albumId=" + this.albumId + ", track=" + this.track + ", dataId=" + this.dataId + ", artists=" + this.artists + "]"; | ||||
| 	} | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| package org.kar.karusic.model; | ||||
| package org.atriasoft.karusic.model; | ||||
| 
 | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.model.User; | ||||
| import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||
| import org.atriasoft.archidata.model.User; | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonInclude; | ||||
| 
 | ||||
							
								
								
									
										32
									
								
								back/src/org/atriasoft/karusic/modelOld/AlbumOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								back/src/org/atriasoft/karusic/modelOld/AlbumOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package org.atriasoft.karusic.modelOld; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataJson; | ||||
| import org.atriasoft.archidata.model.GenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import jakarta.persistence.Column; | ||||
| import jakarta.persistence.Table; | ||||
|  | ||||
| @Table(name = "album") | ||||
| public class AlbumOld extends GenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson() | ||||
| 	public List<ObjectId> covers = null; | ||||
|  | ||||
| 	public Date publication; | ||||
|  | ||||
| 	@Column(nullable = true) | ||||
| 	private final ObjectId oid = new ObjectId(); | ||||
|  | ||||
| 	public ObjectId getOid() { | ||||
| 		return this.oid; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										34
									
								
								back/src/org/atriasoft/karusic/modelOld/ArtistOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								back/src/org/atriasoft/karusic/modelOld/ArtistOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package org.atriasoft.karusic.modelOld; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataJson; | ||||
| import org.atriasoft.archidata.model.GenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
|  | ||||
| import jakarta.persistence.Column; | ||||
| import jakarta.persistence.Table; | ||||
|  | ||||
| @Table(name = "artist") | ||||
| public class ArtistOld extends GenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@DataJson() | ||||
| 	public List<ObjectId> covers = null; | ||||
| 	@Column(length = 256) | ||||
| 	public String firstName = null; | ||||
| 	@Column(length = 256) | ||||
| 	public String surname = null; | ||||
| 	public Date birth = null; | ||||
| 	public Date death = null; | ||||
|  | ||||
| 	@Column(nullable = true) | ||||
| 	private final ObjectId oid = new ObjectId(); | ||||
|  | ||||
| 	public ObjectId getOid() { | ||||
| 		return this.oid; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										53
									
								
								back/src/org/atriasoft/karusic/modelOld/GenderOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								back/src/org/atriasoft/karusic/modelOld/GenderOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| package org.atriasoft.karusic.modelOld; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
| */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataJson; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.GenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
|  | ||||
| import jakarta.persistence.Column; | ||||
| import jakarta.persistence.Table; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
| @Table(name = "gender") | ||||
| public class GenderOld extends GenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@DataJson() | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
|  | ||||
| 	public GenderOld() {} | ||||
|  | ||||
| 	public GenderOld(final String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	public GenderOld(final Long id, final String name) { | ||||
| 		this.id = id; | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	@Column(nullable = true) | ||||
| 	private final ObjectId oid = new ObjectId(); | ||||
|  | ||||
| 	public ObjectId getOid() { | ||||
| 		return this.oid; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										48
									
								
								back/src/org/atriasoft/karusic/modelOld/TrackOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								back/src/org/atriasoft/karusic/modelOld/TrackOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| package org.atriasoft.karusic.modelOld; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
|  */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.atriasoft.archidata.annotation.DataJson; | ||||
| import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||
| import org.atriasoft.archidata.model.Data; | ||||
| import org.atriasoft.archidata.model.GenericDataSoftDelete; | ||||
| import org.bson.types.ObjectId; | ||||
|  | ||||
| import jakarta.persistence.Column; | ||||
| import jakarta.persistence.Table; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
| @Table(name = "track") | ||||
| public class TrackOld extends GenericDataSoftDelete { | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@DataJson() | ||||
| 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||
| 	public Long genderId = null; | ||||
| 	public Long albumId = null; | ||||
| 	public Long track = null; | ||||
| 	public ObjectId dataId = null; | ||||
| 	@DataJson | ||||
| 	public List<Long> artists = null; | ||||
|  | ||||
| 	@Column(nullable = true) | ||||
| 	private final ObjectId oid = new ObjectId(); | ||||
|  | ||||
| 	public ObjectId getOid() { | ||||
| 		return this.oid; | ||||
| 	} | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package org.kar.karusic.util; | ||||
| package org.atriasoft.karusic.util; | ||||
| 
 | ||||
| public class ConfigVariable { | ||||
| 	public static final String BASE_NAME = "ORG_KARUSIC_"; | ||||
| @@ -1,74 +0,0 @@ | ||||
| package org.kar.karusic; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.logging.LogManager; | ||||
|  | ||||
| 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; | ||||
| import org.kar.karusic.api.AlbumResource; | ||||
| import org.kar.karusic.api.ArtistResource; | ||||
| import org.kar.karusic.api.Front; | ||||
| import org.kar.karusic.api.GenderResource; | ||||
| import org.kar.karusic.api.HealthCheck; | ||||
| import org.kar.karusic.api.PlaylistResource; | ||||
| import org.kar.karusic.api.TrackResource; | ||||
| import org.kar.karusic.api.UserResource; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.slf4j.bridge.SLF4JBridgeHandler; | ||||
|  | ||||
| public class WebLauncherLocal extends WebLauncher { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | ||||
|  | ||||
| 	private WebLauncherLocal() {} | ||||
|  | ||||
| 	public static void generateObjects() throws Exception { | ||||
| 		LOGGER.info("Generate APIs"); | ||||
| 		final List<Class<?>> listOfResources = List.of(AlbumResource.class, ArtistResource.class, Front.class, GenderResource.class, HealthCheck.class, PlaylistResource.class, UserResource.class, | ||||
| 				TrackResource.class, DataResource.class, ProxyResource.class); | ||||
| 		final AnalyzeApi api = new AnalyzeApi(); | ||||
| 		api.addAllApi(listOfResources); | ||||
| 		TsGenerateApi.generateApi(api, "../front/src/back-api/"); | ||||
| 		LOGGER.info("Generate APIs (DONE)"); | ||||
| 	} | ||||
|  | ||||
| 	public static void main(final String[] args) throws Exception { | ||||
| 		// Loop-back of logger JDK logging API to SLF4J | ||||
| 		LogManager.getLogManager().reset(); | ||||
| 		SLF4JBridgeHandler.install(); | ||||
| 		// Generate the APIs in type-script | ||||
| 		generateObjects(); | ||||
| 		final WebLauncherLocal launcher = new WebLauncherLocal(); | ||||
| 		launcher.process(); | ||||
| 		launcher.LOGGER.info("end-configure the server & wait finish process:"); | ||||
| 		Thread.currentThread().join(); | ||||
| 		launcher.LOGGER.info("STOP the REST server:"); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void process() throws InterruptedException, DataAccessException { | ||||
| 		if (true) { | ||||
| 			// for local test: | ||||
| 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; | ||||
| 			// ConfigBaseVariable.ssoAdress = "https://atria-soft.org/karso/api/"; | ||||
| 			ConfigBaseVariable.dbPort = "3906"; | ||||
| 			ConfigBaseVariable.testMode = "true"; | ||||
| 		} | ||||
| 		try { | ||||
| 			super.migrateDB(); | ||||
| 		} catch (final Exception e) { | ||||
| 			e.printStackTrace(); | ||||
| 			while (true) { | ||||
| 				LOGGER.error("============================================================================"); | ||||
| 				LOGGER.error("== Migration fail ==> waiting intervention of administrator..."); | ||||
| 				LOGGER.error("============================================================================"); | ||||
| 				Thread.sleep(60 * 60 * 1000); | ||||
| 			} | ||||
| 		} | ||||
| 		super.process(); | ||||
| 	} | ||||
| } | ||||
| @@ -1,101 +0,0 @@ | ||||
| package org.kar.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| 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.addOnSQL.AddOnDataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckFunction; | ||||
| import org.kar.archidata.tools.DataTools; | ||||
| import org.kar.karusic.model.Artist; | ||||
| import org.kar.karusic.model.Artist.ArtistChecker; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.PATCH; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/artist") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class ArtistResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(ArtistResource.class); | ||||
| 	static final ArtistChecker CHECKER = new ArtistChecker(); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Artist get(@PathParam("id") final Long id) throws Exception { | ||||
| 		return DataAccess.get(Artist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Artist> gets() throws Exception { | ||||
| 		return DataAccess.gets(Artist.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Artist post(final Artist data) throws Exception { | ||||
| 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||
| 	} | ||||
|  | ||||
| 	@PATCH | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Artist patch(@PathParam("id") final Long id, @AsyncType(Artist.class) final String jsonRequest) throws Exception { | ||||
| 		DataAccess.updateWithJson(Artist.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||
| 		return DataAccess.get(Artist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||
| 		DataAccess.delete(Artist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{id}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@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 { | ||||
| 		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); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{id}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	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); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,101 +0,0 @@ | ||||
| package org.kar.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| 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.addOnSQL.AddOnDataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckFunction; | ||||
| import org.kar.archidata.tools.DataTools; | ||||
| import org.kar.karusic.model.Gender; | ||||
| import org.kar.karusic.model.Gender.GenderChecker; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.PATCH; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/gender") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class GenderResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(GenderResource.class); | ||||
| 	static final GenderChecker CHECKER = new GenderChecker(); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Gender get(@PathParam("id") final Long id) throws Exception { | ||||
| 		return DataAccess.get(Gender.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Gender> gets() throws Exception { | ||||
| 		return DataAccess.gets(Gender.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Gender post(final Gender data) throws Exception { | ||||
| 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||
| 	} | ||||
|  | ||||
| 	@PATCH | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Gender patch(@PathParam("id") final Long id, @AsyncType(Gender.class) final String jsonRequest) throws Exception { | ||||
| 		DataAccess.updateWithJson(Gender.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||
| 		return DataAccess.get(Gender.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||
| 		DataAccess.delete(Gender.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{id}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@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 { | ||||
| 		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); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{id}/cover/{coverId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	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); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,115 +0,0 @@ | ||||
| package org.kar.karusic.api; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
|  | ||||
| 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.addOnSQL.AddOnDataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckFunction; | ||||
| import org.kar.archidata.tools.DataTools; | ||||
| import org.kar.karusic.model.Playlist; | ||||
| import org.kar.karusic.model.Track.TrackChecker; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import jakarta.annotation.security.RolesAllowed; | ||||
| import jakarta.ws.rs.Consumes; | ||||
| import jakarta.ws.rs.DELETE; | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.PATCH; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
|  | ||||
| @Path("/playlist") | ||||
| @Produces({ MediaType.APPLICATION_JSON }) | ||||
| public class PlaylistResource { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistResource.class); | ||||
| 	static final TrackChecker CHECKER = new TrackChecker(); | ||||
|  | ||||
| 	@GET | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("USER") | ||||
| 	public Playlist get(@PathParam("id") final Long id) throws Exception { | ||||
| 		return DataAccess.get(Playlist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@GET | ||||
| 	@RolesAllowed("USER") | ||||
| 	public List<Playlist> gets() throws Exception { | ||||
| 		return DataAccess.gets(Playlist.class); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Playlist post(final Playlist data) throws Exception { | ||||
| 		return DataAccess.insert(data, new CheckFunction(CHECKER)); | ||||
| 	} | ||||
|  | ||||
| 	@PATCH | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes(MediaType.APPLICATION_JSON) | ||||
| 	public Playlist patch(@PathParam("id") final Long id, @AsyncType(Playlist.class) final String jsonRequest) throws Exception { | ||||
| 		DataAccess.updateWithJson(Playlist.class, id, jsonRequest, new CheckFunction(CHECKER)); | ||||
| 		return DataAccess.get(Playlist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@DELETE | ||||
| 	@Path("{id}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	public void remove(@PathParam("id") final Long id) throws Exception { | ||||
| 		DataAccess.delete(Playlist.class, id); | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{id}/track/{trackId}") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { | ||||
| 		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 { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId); | ||||
| 			return db.get(Playlist.class, id); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@POST | ||||
| 	@Path("{id}/cover") | ||||
| 	@RolesAllowed("ADMIN") | ||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||
| 	@AsyncType(Playlist.class) | ||||
| 	public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) | ||||
| 			throws Exception { | ||||
| 		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 ObjectId coverId) throws Exception { | ||||
| 		try (DBAccess db = DBAccess.createInterface()) { | ||||
| 			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "covers", coverId); | ||||
| 			return DataAccess.get(Playlist.class, id); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,106 +0,0 @@ | ||||
| package org.kar.karusic.migration; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.kar.archidata.dataAccess.DBAccess; | ||||
| import org.kar.archidata.migration.MigrationSqlStep; | ||||
| import org.kar.archidata.model.Data; | ||||
| import org.kar.archidata.model.User; | ||||
| 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.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| public class Initialization extends MigrationSqlStep { | ||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(Initialization.class); | ||||
|  | ||||
| 	public static final int KARSO_INITIALISATION_ID = 1; | ||||
| 	public static final List<Class<?>> CLASSES_BASE = List.of(Album.class, Artist.class, Data.class, Gender.class, Playlist.class, Track.class, User.class); | ||||
|  | ||||
| 	@Override | ||||
| 	public String getName() { | ||||
| 		return "Initialization"; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void generateStep() throws Exception { | ||||
| 		for (final Class<?> clazz : CLASSES_BASE) { | ||||
| 			addClass(clazz); | ||||
| 		} | ||||
|  | ||||
| 		addAction((final DBAccess da) -> { | ||||
| 			final List<Gender> 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")); | ||||
| 			da.insertMultiple(data); | ||||
| 		}); | ||||
| 		// set start increment element to permit to add after default elements | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `album` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `artist` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `gender` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `playlist` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `track` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 		addAction(""" | ||||
| 				ALTER TABLE `user` AUTO_INCREMENT = 1000; | ||||
| 				""", "mysql"); | ||||
| 	} | ||||
|  | ||||
| 	public static void dropAll(final DBAccess da) { | ||||
| 		for (final Class<?> element : CLASSES_BASE) { | ||||
| 			try { | ||||
| 				da.drop(element); | ||||
| 			} catch (final Exception ex) { | ||||
| 				LOGGER.error("Fail to drop table !!!!!!"); | ||||
| 				ex.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static void cleanAll(final DBAccess da) { | ||||
| 		for (final Class<?> element : CLASSES_BASE) { | ||||
| 			try { | ||||
| 				da.cleanAll(element); | ||||
| 			} catch (final Exception ex) { | ||||
| 				LOGGER.error("Fail to clean table !!!!!!"); | ||||
| 				ex.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| package org.kar.karusic.model; | ||||
|  | ||||
| import java.time.LocalDate; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | ||||
| import org.kar.archidata.model.Data; | ||||
| 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) | ||||
| public class Album extends GenericDataSoftDelete { | ||||
| 	public static class AlbumChecker extends CheckJPA<Album> { | ||||
| 		public AlbumChecker() { | ||||
| 			super(Album.class); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson(targetEntity = Data.class) | ||||
| 	@Nullable | ||||
| 	public List<ObjectId> covers = null; | ||||
| 	public LocalDate publication = null; | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| package org.kar.karusic.model; | ||||
|  | ||||
| import java.time.LocalDate; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | ||||
| import org.kar.archidata.model.Data; | ||||
| 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) | ||||
| public class Artist extends GenericDataSoftDelete { | ||||
| 	public static class ArtistChecker extends CheckJPA<Artist> { | ||||
| 		public ArtistChecker() { | ||||
| 			super(Artist.class); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson(targetEntity = Data.class) | ||||
| 	@Nullable | ||||
| 	public List<ObjectId> covers = null; | ||||
| 	@Column(length = 256) | ||||
| 	public String firstName = null; | ||||
| 	@Column(length = 256) | ||||
| 	public String surname = null; | ||||
| 	public LocalDate birth = null; | ||||
| 	public LocalDate death = null; | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return "Artist [id=" + this.id + ", name=" + this.name + ", description=" + this.description + ", covers=" + this.covers + ", firstName=" + this.firstName + ", surname=" + this.surname | ||||
| 				+ ", birth=" + this.birth + ", death=" + this.death + "]"; | ||||
| 	} | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| package org.kar.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
| */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | ||||
| import org.kar.archidata.model.Data; | ||||
| 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) | ||||
| public class Gender extends GenericDataSoftDelete { | ||||
| 	public static class GenderChecker extends CheckJPA<Gender> { | ||||
| 		public GenderChecker() { | ||||
| 			super(Gender.class); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson(targetEntity = Data.class) | ||||
| 	@Nullable | ||||
| 	public List<ObjectId> covers = null; | ||||
|  | ||||
| 	public Gender() {} | ||||
|  | ||||
| 	public Gender(final Long id, final String name) { | ||||
| 		this.id = id; | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| package org.kar.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
| */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | ||||
| import org.kar.archidata.model.Data; | ||||
| 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.FetchType; | ||||
| import jakarta.persistence.ManyToMany; | ||||
| import jakarta.persistence.Table; | ||||
|  | ||||
| @Entity("Playlist") | ||||
| @Table(name = "playlist") | ||||
| @DataIfNotExists | ||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||||
| public class Playlist extends GenericDataSoftDelete { | ||||
| 	public static class PlaylistChecker extends CheckJPA<Playlist> { | ||||
| 		public PlaylistChecker() { | ||||
| 			super(Playlist.class); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson(targetEntity = Data.class) | ||||
| 	@Nullable | ||||
| 	public List<ObjectId> covers = null; | ||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class) | ||||
| 	public List<ObjectId> tracks = null; | ||||
| } | ||||
| @@ -1,66 +0,0 @@ | ||||
| package org.kar.karusic.model; | ||||
| /* | ||||
| CREATE TABLE `node` ( | ||||
|   `id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY, | ||||
|   `deleted` BOOLEAN NOT NULL DEFAULT false, | ||||
|   `create_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been created', | ||||
|   `modify_date` datetime NOT NULL DEFAULT now() COMMENT 'Time the element has been update', | ||||
|   `type` enum("TYPE", "UNIVERS", "SERIE", "SAISON", "MEDIA") NOT NULL DEFAULT 'TYPE', | ||||
|   `name` TEXT COLLATE 'utf8_general_ci' NOT NULL, | ||||
|   `description` TEXT COLLATE 'utf8_general_ci', | ||||
|   `parent_id` bigint | ||||
| ) AUTO_INCREMENT=10; | ||||
|  */ | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bson.types.ObjectId; | ||||
| import org.kar.archidata.annotation.DataIfNotExists; | ||||
| import org.kar.archidata.annotation.DataJson; | ||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | ||||
| import org.kar.archidata.model.Data; | ||||
| 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) | ||||
| public class Track extends GenericDataSoftDelete { | ||||
|  | ||||
| 	public static class TrackChecker extends CheckJPA<Track> { | ||||
| 		public TrackChecker() { | ||||
| 			super(Track.class); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Column(length = 256) | ||||
| 	public String name = null; | ||||
| 	@Column(length = 0) | ||||
| 	public String description = null; | ||||
| 	@Schema(description = "List of Id of the specific covers") | ||||
| 	@DataJson(targetEntity = Data.class) | ||||
| 	@Nullable | ||||
| 	public List<ObjectId> covers = null; | ||||
| 	public Long genderId = null; | ||||
| 	public Long albumId = null; | ||||
| 	public Long track = null; | ||||
| 	public ObjectId dataId = null; | ||||
| 	// @ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class) | ||||
| 	@DataJson | ||||
| 	@Column(length = 0) | ||||
| 	public List<Long> artists = null; | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return "Track [id=" + this.id + ", deleted=" + this.deleted + ", createdAt=" + this.createdAt + ", updatedAt=" + this.updatedAt + ", name=" + this.name + ", description=" + this.description | ||||
| 				+ ", covers=" + this.covers + ", genderId=" + this.genderId + ", albumId=" + this.albumId + ", track=" + this.track + ", dataId=" + this.dataId + ", artists=" + this.artists + "]"; | ||||
| 	} | ||||
| } | ||||
| @@ -10,8 +10,8 @@ | ||||
|                     <pattern>%green(%d{HH:mm:ss.SSS}) %highlight(%-5level) %-30((%file:%line\)): %msg%n</pattern> | ||||
|                 </encoder> | ||||
|             </appender> | ||||
|             <logger name="org.kar.karusic" level="TRACE" /> | ||||
|             <logger name="org.kar.archidata" level="DEBUG" /> | ||||
|             <logger name="org.atriasoft.karusic" level="TRACE" /> | ||||
|             <logger name="org.atriasoft.archidata" level="DEBUG" /> | ||||
|             <root level="INFO"> | ||||
|                 <appender-ref ref="CONSOLE" /> | ||||
|             </root> | ||||
| @@ -32,19 +32,19 @@ | ||||
|     </if> | ||||
|     <if condition="property("LOG_LEVEL_ENV").equals("prod-debug")"> | ||||
|         <then> | ||||
|             <logger name="org.kar.karusic" level="DEBUG" /> | ||||
|             <logger name="org.atriasoft.karusic" level="DEBUG" /> | ||||
|         </then> | ||||
|     </if> | ||||
|     <if condition="property("LOG_LEVEL_ENV").equals("prod-trace")"> | ||||
|         <then> | ||||
|             <logger name="org.kar.karusic" level="TRACE" /> | ||||
|             <logger name="org.kar.archidata" level="DEBUG" /> | ||||
|             <logger name="org.atriasoft.karusic" level="TRACE" /> | ||||
|             <logger name="org.atriasoft.archidata" level="DEBUG" /> | ||||
|         </then> | ||||
|     </if> | ||||
|     <if condition="property("LOG_LEVEL_ENV").equals("prod-trace-full")"> | ||||
|         <then> | ||||
|             <logger name="org.kar.karusic" level="TRACE" /> | ||||
|             <logger name="org.kar.archidata" level="TRACE" /> | ||||
|             <logger name="org.atriasoft.karusic" level="TRACE" /> | ||||
|             <logger name="org.atriasoft.archidata" level="TRACE" /> | ||||
|         </then> | ||||
|     </if> | ||||
| </configuration> | ||||
							
								
								
									
										
											BIN
										
									
								
								back/test/resources/icon-192x192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								back/test/resources/icon-192x192.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 12 KiB | 
| @@ -1,10 +1,11 @@ | ||||
| package test.kar.karusic; | ||||
| package test.atriasoft.karusic; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.kar.archidata.tools.JWTWrapper; | ||||
| import org.atriasoft.archidata.filter.PartRight; | ||||
| import org.atriasoft.archidata.tools.JWTWrapper; | ||||
| 
 | ||||
| public class Common { | ||||
| 	static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", Boolean.TRUE))); | ||||
| 	static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", Boolean.TRUE, "ADMIN", Boolean.TRUE))); | ||||
| 	static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", PartRight.READ))); | ||||
| 	static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karusic", Map.of("karusic", Map.of("USER", PartRight.READ_WRITE, "ADMIN", PartRight.READ_WRITE))); | ||||
| } | ||||
| @@ -1,19 +1,12 @@ | ||||
| package test.kar.karusic; | ||||
| package test.atriasoft.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.atriasoft.archidata.dataAccess.DBAccess; | ||||
| import org.atriasoft.archidata.db.DbConfig; | ||||
| import org.atriasoft.archidata.db.DbIoFactory; | ||||
| import org.atriasoft.archidata.exception.DataAccessException; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @@ -39,14 +32,6 @@ public class ConfigureDb { | ||||
| 		ConfigBaseVariable.apiAdress = "http://127.0.0.1:12342/test/api/"; | ||||
| 		// Enable the test mode permit to access to the test token (never use it in production). | ||||
| 		ConfigBaseVariable.testMode = "true"; | ||||
| 		final List<Class<?>> listObject = List.of( // | ||||
| 				Album.class, // | ||||
| 				Artist.class, // | ||||
| 				Gender.class, // | ||||
| 				Playlist.class, // | ||||
| 				Track.class, // | ||||
| 				UserKarusic.class // | ||||
| 		); | ||||
| 		if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) { | ||||
| 			ConfigBaseVariable.dbType = "sqlite"; | ||||
| 			ConfigBaseVariable.bdDatabase = null; | ||||
| @@ -59,15 +44,15 @@ public class ConfigureDb { | ||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||
| 		} else if ("MY-SQL".equalsIgnoreCase(modeTest)) { | ||||
| 			ConfigBaseVariable.dbType = "mysql"; | ||||
| 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||
| 			ConfigBaseVariable.bdDatabase = "test.atriasoftusic_db"; | ||||
| 			ConfigBaseVariable.dbPort = "3906"; | ||||
| 			ConfigBaseVariable.dbUser = "root"; | ||||
| 		} else if ("MONGO".equalsIgnoreCase(modeTest)) { | ||||
| 			ConfigBaseVariable.dbType = "mongo"; | ||||
| 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||
| 			ConfigBaseVariable.bdDatabase = "test.atriasoftusic_db"; | ||||
| 		} else { | ||||
| 			// User local modification ... | ||||
| 			ConfigBaseVariable.bdDatabase = "test_karusic_db"; | ||||
| 			ConfigBaseVariable.bdDatabase = "test.atriasoftusic_db"; | ||||
| 			ConfigBaseVariable.dbPort = "3906"; | ||||
| 			ConfigBaseVariable.dbUser = "root"; | ||||
| 		} | ||||
							
								
								
									
										15
									
								
								back/test/src/test/atriasoft/karusic/ResourceUtils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								back/test/src/test/atriasoft/karusic/ResourceUtils.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| package test.atriasoft.karusic; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.Objects; | ||||
|  | ||||
| public class ResourceUtils { | ||||
|  | ||||
| 	public static File getResourceFile(final String resourcePath) throws IOException { | ||||
| 		final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||||
| 		final URL resource = Objects.requireNonNull(classLoader.getResource(resourcePath), "Fichier non trouvé : " + resourcePath); | ||||
| 		return new File(resource.getFile()); | ||||
| 	} | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package test.kar.karusic; | ||||
| package test.atriasoft.karusic; | ||||
| 
 | ||||
| import org.junit.jupiter.api.extension.ConditionEvaluationResult; | ||||
| import org.junit.jupiter.api.extension.ExecutionCondition; | ||||
| @@ -1,21 +1,24 @@ | ||||
| package test.kar.karusic; | ||||
| package test.atriasoft.karusic; | ||||
| 
 | ||||
| import org.atriasoft.archidata.exception.RESTErrorResponseException; | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.archidata.tools.RESTApi; | ||||
| import org.atriasoft.karusic.api.HealthCheck.HealthResult; | ||||
| import org.junit.jupiter.api.AfterAll; | ||||
| import org.junit.jupiter.api.Assertions; | ||||
| import org.junit.jupiter.api.BeforeAll; | ||||
| import org.junit.jupiter.api.MethodOrderer; | ||||
| import org.junit.jupiter.api.Order; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.TestMethodOrder; | ||||
| import org.junit.jupiter.api.extension.ExtendWith; | ||||
| import org.kar.archidata.tools.ConfigBaseVariable; | ||||
| import org.kar.archidata.tools.RESTApi; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| @ExtendWith(StepwiseExtension.class) | ||||
| @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||
| public class TestBase { | ||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(TestBase.class); | ||||
| 	public final static String ENDPOINT_NAME = "species/"; | ||||
| public class TestHealthCheck { | ||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(TestHealthCheck.class); | ||||
| 
 | ||||
| 	static WebLauncherTest webInterface = null; | ||||
| 	static RESTApi api = null; | ||||
| @@ -40,9 +43,17 @@ public class TestBase { | ||||
| 		ConfigureDb.clear(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Order(1) | ||||
| 	@Test | ||||
| 	public static void TestEmpty() throws Exception { | ||||
| 	public void checkHealthCheck() throws Exception { | ||||
| 		final HealthResult result = api.request("health_check").get().fetch(HealthResult.class); | ||||
| 		Assertions.assertEquals(result.value(), "alive and kicking"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Order(2) | ||||
| 	@Test | ||||
| 	public void checkHealthCheckWrongAPI() throws Exception { | ||||
| 		Assertions.assertThrows(RESTErrorResponseException.class, () -> api.request("health_check_kaboom").get().fetch()); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										115
									
								
								back/test/src/test/atriasoft/karusic/TestTrack.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								back/test/src/test/atriasoft/karusic/TestTrack.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| package test.atriasoft.karusic; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.http.HttpResponse; | ||||
| import java.nio.file.Files; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||
| import org.atriasoft.archidata.tools.RESTApi; | ||||
| import org.atriasoft.karusic.model.Track; | ||||
| import org.junit.jupiter.api.AfterAll; | ||||
| import org.junit.jupiter.api.Assertions; | ||||
| import org.junit.jupiter.api.BeforeAll; | ||||
| import org.junit.jupiter.api.MethodOrderer; | ||||
| import org.junit.jupiter.api.Order; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.TestMethodOrder; | ||||
| import org.junit.jupiter.api.extension.ExtendWith; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| @ExtendWith(StepwiseExtension.class) | ||||
| @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||
| public class TestTrack { | ||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(TestTrack.class); | ||||
| 	public final static String ENDPOINT_NAME = "track"; | ||||
| 	public final static String ENDPOINT_DATA_NAME = "data"; | ||||
|  | ||||
| 	static WebLauncherTest webInterface = null; | ||||
| 	static RESTApi api = null; | ||||
|  | ||||
| 	@BeforeAll | ||||
| 	public static void configureWebServer() throws Exception { | ||||
| 		ConfigureDb.configure(); | ||||
| 		LOGGER.info("configure server ..."); | ||||
| 		webInterface = new WebLauncherTest(); | ||||
| 		LOGGER.info("Create BDD"); | ||||
| 		webInterface.migrateDB(); | ||||
| 		LOGGER.info("Start REST (BEGIN)"); | ||||
| 		webInterface.process(); | ||||
| 		LOGGER.info("Start REST (DONE)"); | ||||
| 		api = new RESTApi(ConfigBaseVariable.apiAdress); | ||||
| 		api.setToken(Common.ADMIN_TOKEN); | ||||
| 	} | ||||
|  | ||||
| 	@AfterAll | ||||
| 	public static void stopWebServer() throws Exception { | ||||
| 		LOGGER.info("Kill the web server"); | ||||
| 		webInterface.stop(); | ||||
| 		webInterface = null; | ||||
| 		ConfigureDb.clear(); | ||||
| 	} | ||||
|  | ||||
| 	public static boolean compareResponseWithFile(final byte[] responseBody, final File file) throws IOException { | ||||
| 		final byte[] fileBytes = Files.readAllBytes(file.toPath()); | ||||
| 		if (responseBody == null && fileBytes == null) { | ||||
| 			return true; | ||||
| 		} | ||||
| 		if (responseBody == null || fileBytes == null) { | ||||
| 			return false; | ||||
| 		} | ||||
| 		if (responseBody.length != fileBytes.length) { | ||||
| 			LOGGER.error("The data have not the same size: {} != {}(ref)", responseBody.length, fileBytes.length); | ||||
| 			return false; | ||||
| 		} | ||||
| 		for (int iii = 0; iii < responseBody.length; iii++) { | ||||
| 			if (responseBody[iii] != fileBytes[iii]) { | ||||
| 				LOGGER.error("Detect error at the {}/{} element", iii, responseBody.length); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	@Order(1) | ||||
| 	@Test | ||||
| 	public void createTrack() throws Exception { | ||||
| 		final File dataToUpload = ResourceUtils.getResourceFile("icon-192x192.png"); | ||||
| 		final Track data = new Track(); | ||||
| 		data.name = "test track"; | ||||
| 		data.description = "My track description"; | ||||
| 		final Map<String, Object> multipart = new HashMap<>(); | ||||
| 		multipart.put("title", data.name); | ||||
| 		multipart.put("genderId", null); | ||||
| 		multipart.put("artistId", null); | ||||
| 		multipart.put("albumId", null); | ||||
| 		multipart.put("trackId", 9); | ||||
| 		multipart.put("file", dataToUpload); | ||||
|  | ||||
| 		final Track inserted = api.request(TestTrack.ENDPOINT_NAME, "upload").post().bodyMultipart(multipart).fetch(Track.class); | ||||
|  | ||||
| 		Assertions.assertNotNull(inserted); | ||||
| 		Assertions.assertNotNull(inserted.oid); | ||||
| 		// Assertions.assertTrue(inserted.oid >= 0); | ||||
| 		Assertions.assertNull(inserted.updatedAt); | ||||
| 		Assertions.assertNull(inserted.createdAt); | ||||
| 		Assertions.assertNull(inserted.deleted); | ||||
| 		Assertions.assertNotNull(inserted.name); | ||||
| 		Assertions.assertEquals(data.name, inserted.name); | ||||
| 		Assertions.assertNotNull(inserted.dataId); | ||||
|  | ||||
| 		// Retrieve Data: | ||||
| 		final HttpResponse<byte[]> retreiveData = api.request(TestTrack.ENDPOINT_DATA_NAME, inserted.dataId.toString()).get().fetchByte(); | ||||
| 		Assertions.assertNotNull(retreiveData); | ||||
| 		Assertions.assertEquals(200, retreiveData.statusCode()); | ||||
| 		Assertions.assertEquals("11999", retreiveData.headers().firstValue("content-length").orElse(null)); | ||||
| 		final String contentType = retreiveData.headers().firstValue("content-type").orElse(null); | ||||
| 		Assertions.assertEquals("image/png", contentType); | ||||
| 		Assertions.assertTrue(compareResponseWithFile(retreiveData.body(), dataToUpload)); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| 
 | ||||
| package test.kar.karusic; | ||||
| package test.atriasoft.karusic; | ||||
| 
 | ||||
| import org.kar.karusic.WebLauncher; | ||||
| import org.atriasoft.karusic.WebLauncher; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
							
								
								
									
										1
									
								
								front/.env
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								front/.env
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| NODE_ENV=development | ||||
| @@ -4,23 +4,11 @@ import { Box } from '@chakra-ui/react'; | ||||
| import { ChakraProvider } from '@chakra-ui/react'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
|  | ||||
| import theme from '../src/theme'; | ||||
|  | ||||
| // .storybook/preview.js | ||||
| export const parameters = { | ||||
|   options: { | ||||
|     storySort: { | ||||
|       order: ['StyleGuide', 'Components', 'Fields', 'App Layout'], | ||||
|     }, | ||||
|   }, | ||||
|   actions: {}, | ||||
|   layout: 'fullscreen', | ||||
|   backgrounds: { disable: true, grid: { disable: true } }, | ||||
|   chakra: { | ||||
|     theme, | ||||
|   }, | ||||
| }; | ||||
| import { ColorModeProvider } from '../src/components/ui/color-mode'; | ||||
| import { Toaster } from '../src/components/ui/toaster'; | ||||
| import { systemTheme } from '../src/theme/theme'; | ||||
|  | ||||
| // . | ||||
| const DocumentationWrapper = ({ children }) => { | ||||
|   return ( | ||||
|     <Box id="start-ui-storybook-wrapper" p="4" pb="8" flex="1"> | ||||
| @@ -31,13 +19,16 @@ const DocumentationWrapper = ({ children }) => { | ||||
|  | ||||
| export const decorators = [ | ||||
|   (Story, context) => ( | ||||
|     <ChakraProvider theme={theme}> | ||||
|       {/* Using MemoryRouter to avoid route clashing with Storybook */} | ||||
|       <MemoryRouter> | ||||
|         <DocumentationWrapper> | ||||
|           <Story {...context} /> | ||||
|         </DocumentationWrapper> | ||||
|       </MemoryRouter> | ||||
|     </ChakraProvider> | ||||
|     <ColorModeProvider> | ||||
|       <ChakraProvider value={systemTheme}> | ||||
|         {/* Using MemoryRouter to avoid route clashing with Storybook */} | ||||
|         <MemoryRouter> | ||||
|           <DocumentationWrapper> | ||||
|             <Story {...context} /> | ||||
|           </DocumentationWrapper> | ||||
|         </MemoryRouter> | ||||
|         <Toaster /> | ||||
|       </ChakraProvider> | ||||
|     </ColorModeProvider> | ||||
|   ), | ||||
| ]; | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| { | ||||
|   "display": "2025-01-14", | ||||
|   "version": "0.0.1-dev\n - 2025-01-14T20:19:20+01:00", | ||||
|   "commit": "0.0.1-dev\n", | ||||
|   "date": "2025-01-14T20:19:20+01:00" | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
| const dayjs = require('dayjs'); | ||||
|  | ||||
| const fs = require('fs'); | ||||
|  | ||||
| const generateAppBuild = () => { | ||||
|   const getVersion = () => fs.readFileSync('version.txt', 'utf8'); | ||||
|  | ||||
|   const commit = process.env.VERCEL_GIT_COMMIT_SHA | ||||
|     ? process.env.VERCEL_GIT_COMMIT_SHA | ||||
|     : getVersion(); | ||||
|  | ||||
|   const appBuildContent = { | ||||
|     display: `${dayjs().format('YYYY-MM-DD')}`, | ||||
|     version: `${commit} - ${dayjs().format()}`, | ||||
|     commit, | ||||
|     date: dayjs().format(), | ||||
|   }; | ||||
|  | ||||
|   fs.writeFileSync( | ||||
|     './app-build.json', | ||||
|     JSON.stringify(appBuildContent, null, 2) | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| generateAppBuild(); | ||||
							
								
								
									
										10637
									
								
								front/config sample.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10637
									
								
								front/config sample.yaml
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -2,6 +2,7 @@ | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <link rel="manifest" href="/manifest.json" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Karusic</title> | ||||
|     <link rel="icon" href="/favicon.ico" /> | ||||
|   | ||||
| @@ -3,16 +3,7 @@ import type { KnipConfig } from 'knip'; | ||||
| const config: KnipConfig = { | ||||
|   // Ignoring mostly shell binaries | ||||
|   ignoreBinaries: ['export', 'sleep'], | ||||
|   ignore: [ | ||||
|     // Related to tests | ||||
|     'tests/**', | ||||
|     '**.conf.js', | ||||
|     'steps.d.ts', | ||||
|     'steps_file.js', | ||||
|     'env_ci/codecept.conf.js', | ||||
|     // Generic components are useful. | ||||
|     'src/components/**', | ||||
|   ], | ||||
|   ignore: [], | ||||
| }; | ||||
|  | ||||
| export default config; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
|     "test": "vitest run", | ||||
|     "test:watch": "vitest watch", | ||||
|     "build": "tsc && vite build", | ||||
|     "static:build": "node build.js && pnpm build", | ||||
|     "static:build": "pnpm build", | ||||
|     "dev": "vite", | ||||
|     "pretty": "prettier -w .", | ||||
|     "lint": "pnpm tsc --noEmit", | ||||
| @@ -29,65 +29,65 @@ | ||||
|     "*.{ts,tsx,js,jsx,json}": "prettier --write" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@chakra-ui/anatomy": "2.3.4", | ||||
|     "@chakra-ui/cli": "3.3.1", | ||||
|     "@chakra-ui/react": "3.3.1", | ||||
|     "react-speech-recognition": "4.0.1", | ||||
|     "regenerator-runtime": "0.14.1", | ||||
|     "@trivago/prettier-plugin-sort-imports": "5.2.2", | ||||
|     "@chakra-ui/cli": "3.17.0", | ||||
|     "@chakra-ui/react": "3.17.0", | ||||
|     "@emotion/react": "11.14.0", | ||||
|     "@emotion/styled": "11.14.0", | ||||
|     "allotment": "1.20.2", | ||||
|     "allotment": "1.20.3", | ||||
|     "css-mediaquery": "0.1.2", | ||||
|     "dayjs": "1.11.13", | ||||
|     "history": "5.3.0", | ||||
|     "next-themes": "^0.4.4", | ||||
|     "react": "18.3.1", | ||||
|     "react-dom": "18.3.1", | ||||
|     "next-themes": "^0.4.6", | ||||
|     "react": "19.1.0", | ||||
|     "react-dom": "19.1.0", | ||||
|     "react-error-boundary": "5.0.0", | ||||
|     "react-icons": "5.4.0", | ||||
|     "react-router-dom": "7.1.1", | ||||
|     "react-select": "5.9.0", | ||||
|     "react-icons": "5.5.0", | ||||
|     "react-router-dom": "7.5.3", | ||||
|     "react-select": "5.10.1", | ||||
|     "react-use": "17.6.0", | ||||
|     "zod": "3.24.1", | ||||
|     "zod": "3.24.3", | ||||
|     "zustand": "5.0.3" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@chakra-ui/styled-system": "^2.12.0", | ||||
|     "@playwright/test": "1.49.1", | ||||
|     "@storybook/addon-actions": "8.4.7", | ||||
|     "@storybook/addon-essentials": "8.4.7", | ||||
|     "@storybook/addon-links": "8.4.7", | ||||
|     "@storybook/addon-mdx-gfm": "8.4.7", | ||||
|     "@storybook/react": "8.4.7", | ||||
|     "@storybook/react-vite": "8.4.7", | ||||
|     "@storybook/theming": "8.4.7", | ||||
|     "@playwright/test": "1.52.0", | ||||
|     "@storybook/addon-actions": "8.6.12", | ||||
|     "@storybook/addon-essentials": "8.6.12", | ||||
|     "@storybook/addon-links": "8.6.12", | ||||
|     "@storybook/addon-mdx-gfm": "8.6.12", | ||||
|     "@storybook/react": "8.6.12", | ||||
|     "@storybook/react-vite": "8.6.12", | ||||
|     "@storybook/theming": "8.6.12", | ||||
|     "@testing-library/jest-dom": "6.6.3", | ||||
|     "@testing-library/react": "16.1.0", | ||||
|     "@testing-library/user-event": "14.5.2", | ||||
|     "@trivago/prettier-plugin-sort-imports": "5.2.1", | ||||
|     "@testing-library/react": "16.3.0", | ||||
|     "@testing-library/user-event": "14.6.1", | ||||
|     "@trivago/prettier-plugin-sort-imports": "5.2.2", | ||||
|     "@types/jest": "29.5.14", | ||||
|     "@types/node": "22.10.6", | ||||
|     "@types/react": "18.3.8", | ||||
|     "@types/react-dom": "18.3.0", | ||||
|     "@typescript-eslint/eslint-plugin": "8.20.0", | ||||
|     "@typescript-eslint/parser": "8.20.0", | ||||
|     "@vitejs/plugin-react": "4.3.4", | ||||
|     "eslint": "9.18.0", | ||||
|     "eslint-plugin-codeceptjs": "1.3.0", | ||||
|     "@types/node": "22.15.3", | ||||
|     "@types/react": "19.1.2", | ||||
|     "@types/react-dom": "19.1.3", | ||||
|     "@typescript-eslint/eslint-plugin": "8.31.1", | ||||
|     "@typescript-eslint/parser": "8.31.1", | ||||
|     "@vitejs/plugin-react": "4.4.1", | ||||
|     "eslint": "9.25.1", | ||||
|     "eslint-plugin-import": "2.31.0", | ||||
|     "eslint-plugin-react": "7.37.4", | ||||
|     "eslint-plugin-react-hooks": "5.1.0", | ||||
|     "eslint-plugin-storybook": "0.11.2", | ||||
|     "eslint-plugin-react": "7.37.5", | ||||
|     "eslint-plugin-react-hooks": "5.2.0", | ||||
|     "eslint-plugin-storybook": "0.12.0", | ||||
|     "jest": "29.7.0", | ||||
|     "jest-environment-jsdom": "29.7.0", | ||||
|     "knip": "5.42.0", | ||||
|     "lint-staged": "15.3.0", | ||||
|     "npm-check-updates": "^17.1.13", | ||||
|     "prettier": "3.4.2", | ||||
|     "puppeteer": "24.0.0", | ||||
|     "react-is": "19.0.0", | ||||
|     "storybook": "8.4.7", | ||||
|     "knip": "5.52.0", | ||||
|     "lint-staged": "15.5.1", | ||||
|     "npm-check-updates": "^18.0.1", | ||||
|     "prettier": "3.5.3", | ||||
|     "puppeteer": "24.7.2", | ||||
|     "react-is": "19.1.0", | ||||
|     "storybook": "8.6.12", | ||||
|     "ts-node": "10.9.2", | ||||
|     "typescript": "5.7.3", | ||||
|     "vite": "6.0.7", | ||||
|     "vitest": "2.1.8" | ||||
|     "typescript": "5.8.3", | ||||
|     "vite": "6.3.4", | ||||
|     "vitest": "3.1.2" | ||||
|   } | ||||
| } | ||||
| } | ||||
|   | ||||
							
								
								
									
										5948
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5948
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								front/public/icons/icon-192x192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								front/public/icons/icon-192x192.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								front/public/icons/icon-512x512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								front/public/icons/icon-512x512.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 41 KiB | 
							
								
								
									
										21
									
								
								front/public/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								front/public/manifest.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| { | ||||
|   "name": "Karusic", | ||||
|   "short_name": "Karusic", | ||||
|   "description": "(K)angaroo (A)nd (R)abbit m(usic) is a music streaming", | ||||
|   "start_url": "/karusic/", | ||||
|   "display": "standalone", | ||||
|   "background_color": "#000000", | ||||
|   "theme_color": "#FFFFFF", | ||||
|   "icons": [ | ||||
|     { | ||||
|       "src": "/karusic/icons/icon-192x192.png", | ||||
|       "sizes": "192x192", | ||||
|       "type": "image/png" | ||||
|     }, | ||||
|     { | ||||
|       "src": "/karusic/icons/icon-512x512.png", | ||||
|       "sizes": "512x512", | ||||
|       "type": "image/png" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -1,132 +1,19 @@ | ||||
| import { useState } from 'react'; | ||||
| import { ErrorBoundary } from '@/errors/ErrorBoundary'; | ||||
|  | ||||
| import { | ||||
|   Box, | ||||
|   Button, | ||||
|   ChakraProvider, | ||||
|   DialogBody, | ||||
|   DialogContent, | ||||
|   DialogFooter, | ||||
|   DialogHeader, | ||||
|   DialogRoot, | ||||
|   DialogTrigger, | ||||
|   SelectContent, | ||||
|   SelectItem, | ||||
|   SelectRoot, | ||||
|   SelectTrigger, | ||||
|   SelectValueText, | ||||
|   Stack, | ||||
|   Text, | ||||
|   useDisclosure, | ||||
| } from '@chakra-ui/react'; | ||||
|  | ||||
| import { environment } from '@/environment'; | ||||
| import { App as SpaApp } from '@/scene/App'; | ||||
| import { USERS, USERS_COLLECTION } from '@/service/session'; | ||||
| import { hashLocalData } from '@/utils/sso'; | ||||
| import { Toaster } from './components/ui/toaster'; | ||||
| import { systemTheme } from './theme/theme'; | ||||
|  | ||||
| const AppEnvHint = () => { | ||||
|   const dialog = useDisclosure(); | ||||
|   const [selectUserTest, setSelectUserTest] = useState<string>('NO_USER'); | ||||
|   //const setUser = useRightsStore((store) => store.setUser); | ||||
|   const buildEnv = | ||||
|     process.env.NODE_ENV === 'development' | ||||
|       ? 'Development' | ||||
|       : import.meta.env.VITE_DEV_ENV_NAME; | ||||
|   const envName: Array<string> = []; | ||||
|   !!buildEnv && envName.push(buildEnv); | ||||
|   if (!envName.length) { | ||||
|     return null; | ||||
|   } | ||||
|   const handleChange = (selectedOption) => { | ||||
|     console.log(`SELECT: [${selectedOption.target.value}]`); | ||||
|     setSelectUserTest(selectedOption.target.value); | ||||
|   }; | ||||
|   const onClose = () => { | ||||
|     dialog.onClose(); | ||||
|     if (selectUserTest == 'NO_USER') { | ||||
|       window.location.href = `/${environment.applName}/sso/${hashLocalData()}/false/__LOGOUT__`; | ||||
|     } else { | ||||
|       window.location.href = `/${environment.applName}/sso/${hashLocalData()}/true/${USERS[selectUserTest]}`; | ||||
|     } | ||||
|   }; | ||||
| import { AudioPlayer } from './components'; | ||||
| import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment'; | ||||
| import { AppRoutes } from './scene/AppRoutes'; | ||||
| import { ServiceContextProvider } from './service/ServiceContext'; | ||||
|  | ||||
| export const App = () => { | ||||
|   return ( | ||||
|     <> | ||||
|       <Box | ||||
|         zIndex="100000" | ||||
|         position="fixed" | ||||
|         top="0" | ||||
|         insetStart="0" | ||||
|         insetEnd="0" | ||||
|         h="2px" | ||||
|         bg="warning.400" | ||||
|         as="button" | ||||
|         cursor="pointer" | ||||
|         data-test-id="devtools" | ||||
|         onClick={dialog.onOpen} | ||||
|       > | ||||
|         <Text | ||||
|           position="fixed" | ||||
|           top="0" | ||||
|           insetStart="4" | ||||
|           bg="warning.400" | ||||
|           color="warning.900" | ||||
|           fontSize="0.6rem" | ||||
|           fontWeight="bold" | ||||
|           px="10px" | ||||
|           marginLeft="25%" | ||||
|           borderBottomStartRadius="sm" | ||||
|           borderBottomEndRadius="sm" | ||||
|           textTransform="uppercase" | ||||
|         > | ||||
|           {envName.join(' : ')} | ||||
|         </Text> | ||||
|       </Box> | ||||
|       <DialogRoot open={dialog.open} onOpenChange={dialog.onClose}> | ||||
|         <DialogContent> | ||||
|           <DialogHeader>Outils développeurs</DialogHeader> | ||||
|           <DialogTrigger asChild> | ||||
|             <Button variant="outline" size="sm"> | ||||
|               {dialog.open ? "Close" : "Open"} Dialog | ||||
|             </Button> | ||||
|           </DialogTrigger> | ||||
|           <DialogBody> | ||||
|             <Stack> | ||||
|               <Text>User</Text> | ||||
|               <SelectRoot onChange={handleChange} collection={USERS_COLLECTION}> | ||||
|                 <SelectTrigger> | ||||
|                   <SelectValueText placeholder="Select test user" /> | ||||
|                 </SelectTrigger> | ||||
|                 <SelectContent> | ||||
|                   {USERS_COLLECTION.items.map((value) => ( | ||||
|                     <SelectItem item={value} key={value.value}> | ||||
|                       {value.label} | ||||
|                     </SelectItem> | ||||
|                   ))} | ||||
|                 </SelectContent> | ||||
|               </SelectRoot> | ||||
|             </Stack> | ||||
|           </DialogBody> | ||||
|           <DialogFooter> | ||||
|             <Button onClick={onClose}>Apply</Button> | ||||
|           </DialogFooter> | ||||
|         </DialogContent> | ||||
|       </DialogRoot> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| const App = () => { | ||||
|  | ||||
|   return ( | ||||
|     <ChakraProvider value={systemTheme}> | ||||
|       <AppEnvHint /> | ||||
|       <SpaApp /> | ||||
|       <Toaster /> | ||||
|     </ChakraProvider> | ||||
|     <ServiceContextProvider> | ||||
|       <EnvDevelopment /> | ||||
|       <ErrorBoundary> | ||||
|         <AppRoutes /> | ||||
|       </ErrorBoundary> | ||||
|       <AudioPlayer /> | ||||
|     </ServiceContextProvider> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,72 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    stroke="currentColor" | ||||
|    fill="currentColor" | ||||
|    stroke-width="0" | ||||
|    viewBox="0 0 24 24" | ||||
|    height="250px" | ||||
|    width="250px" | ||||
|    version="1.1" | ||||
|    id="svg2" | ||||
|    sodipodi:docname="404.svg" | ||||
|    inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="namedview2" | ||||
|      pagecolor="#505050" | ||||
|      bordercolor="#eeeeee" | ||||
|      borderopacity="1" | ||||
|      inkscape:showpageshadow="0" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pagecheckerboard="0" | ||||
|      inkscape:deskcolor="#d1d1d1" | ||||
|      showgrid="true" | ||||
|      inkscape:zoom="3.448" | ||||
|      inkscape:cx="134.28074" | ||||
|      inkscape:cy="125" | ||||
|      inkscape:window-width="1918" | ||||
|      inkscape:window-height="1044" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="17" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:current-layer="svg2"> | ||||
|     <inkscape:grid | ||||
|        id="grid2" | ||||
|        units="px" | ||||
|        originx="0" | ||||
|        originy="0" | ||||
|        spacingx="0.096" | ||||
|        spacingy="0.096" | ||||
|        empcolor="#0099e5" | ||||
|        empopacity="0.30196078" | ||||
|        color="#0099e5" | ||||
|        opacity="0.14901961" | ||||
|        empspacing="5" | ||||
|        dotted="false" | ||||
|        gridanglex="30" | ||||
|        gridanglez="30" | ||||
|        visible="true" /> | ||||
|   </sodipodi:namedview> | ||||
|   <path | ||||
|      fill="none" | ||||
|      d="M0 0h24v24H0z" | ||||
|      id="path1" /> | ||||
|   <path | ||||
|      d="M13 10h5l3-3-3-3h-5V2h-2v2H4v6h7v2H6l-3 3 3 3h5v4h2v-4h7v-6h-7z" | ||||
|      id="path2" /> | ||||
|   <path | ||||
|      id="rect2" | ||||
|      style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.384;stroke-linecap:square" | ||||
|      d="M 17.394219,5.0400499 19.459554,6.9903325 17.438107,9.0722051 4.9259029,9.0569946 4.9284452,5.0338374 Z" | ||||
|      sodipodi:nodetypes="cccccc" /> | ||||
|   <path | ||||
|      id="rect2-3" | ||||
|      style="fill:#f8fefb;fill-opacity:1;stroke:none;stroke-width:0.384;stroke-linecap:square" | ||||
|      d="m 6.5757719,13.021525 -2.065335,1.950283 2.021447,2.081873 12.5122061,-0.01521 -0.0025,-4.023157 z" | ||||
|      sodipodi:nodetypes="cccccc" /> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 2.1 KiB | 
| @@ -13,9 +13,9 @@ import { | ||||
| import { z as zod } from "zod" | ||||
| import { | ||||
| 	Album, | ||||
| 	AlbumWrite, | ||||
| 	Long, | ||||
| 	UUID, | ||||
| 	AlbumCreate, | ||||
| 	AlbumUpdate, | ||||
| 	ObjectId, | ||||
| 	ZodAlbum, | ||||
| 	isAlbum, | ||||
| } from "../model"; | ||||
| @@ -31,12 +31,12 @@ export namespace AlbumResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{id}", | ||||
| 				endPoint: "/album/{oid}", | ||||
| 				requestType: HTTPRequestModel.GET, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| @@ -75,32 +75,6 @@ export namespace AlbumResource { | ||||
| 			restConfig, | ||||
| 		}, isGetsTypeReturn); | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * Update a specific album | ||||
| 	 */ | ||||
| 	export function patch({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 		data: AlbumWrite, | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{id}", | ||||
| 				requestType: HTTPRequestModel.PATCH, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isAlbum); | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * Add an album (when all the data already exist) | ||||
| 	 */ | ||||
| @@ -109,7 +83,7 @@ export namespace AlbumResource { | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		data: AlbumWrite, | ||||
| 		data: AlbumCreate, | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -122,6 +96,32 @@ export namespace AlbumResource { | ||||
| 			data, | ||||
| 		}, isAlbum); | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * Update a specific album | ||||
| 	 */ | ||||
| 	export function put({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: AlbumUpdate, | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{oid}", | ||||
| 				requestType: HTTPRequestModel.PUT, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isAlbum); | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * Remove a specific album | ||||
| 	 */ | ||||
| @@ -131,12 +131,12 @@ export namespace AlbumResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<void> { | ||||
| 		return RESTRequestVoid({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{id}", | ||||
| 				endPoint: "/album/{oid}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 			}, | ||||
| @@ -153,13 +153,13 @@ export namespace AlbumResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			coverId: UUID, | ||||
| 			id: Long, | ||||
| 			coverId: ObjectId, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{id}/cover/{coverId}", | ||||
| 				endPoint: "/album/{oid}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -179,7 +179,7 @@ export namespace AlbumResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: { | ||||
| 			file?: File, | ||||
| @@ -189,7 +189,7 @@ export namespace AlbumResource { | ||||
| 	}): Promise<Album> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/album/{id}/cover", | ||||
| 				endPoint: "/album/{oid}/cover", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
|   | ||||
| @@ -13,8 +13,8 @@ import { | ||||
| import { z as zod } from "zod" | ||||
| import { | ||||
| 	Artist, | ||||
| 	ArtistWrite, | ||||
| 	Long, | ||||
| 	ArtistCreate, | ||||
| 	ArtistUpdate, | ||||
| 	ObjectId, | ||||
| 	ZodArtist, | ||||
| 	isArtist, | ||||
| @@ -28,12 +28,12 @@ export namespace ArtistResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{id}", | ||||
| 				endPoint: "/artist/{oid}", | ||||
| 				requestType: HTTPRequestModel.GET, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| @@ -69,35 +69,12 @@ export namespace ArtistResource { | ||||
| 			restConfig, | ||||
| 		}, isGetsTypeReturn); | ||||
| 	}; | ||||
| 	export function patch({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 		data: ArtistWrite, | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{id}", | ||||
| 				requestType: HTTPRequestModel.PATCH, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isArtist); | ||||
| 	}; | ||||
| 	export function post({ | ||||
| 			restConfig, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		data: ArtistWrite, | ||||
| 		data: ArtistCreate, | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -110,18 +87,41 @@ export namespace ArtistResource { | ||||
| 			data, | ||||
| 		}, isArtist); | ||||
| 	}; | ||||
| 	export function put({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: ArtistUpdate, | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{oid}", | ||||
| 				requestType: HTTPRequestModel.PUT, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isArtist); | ||||
| 	}; | ||||
| 	export function remove({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<void> { | ||||
| 		return RESTRequestVoid({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{id}", | ||||
| 				endPoint: "/artist/{oid}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 			}, | ||||
| @@ -136,12 +136,12 @@ export namespace ArtistResource { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			coverId: ObjectId, | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{id}/cover/{coverId}", | ||||
| 				endPoint: "/artist/{oid}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -158,7 +158,7 @@ export namespace ArtistResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: { | ||||
| 			file?: File, | ||||
| @@ -168,7 +168,7 @@ export namespace ArtistResource { | ||||
| 	}): Promise<Artist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/artist/{id}/cover", | ||||
| 				endPoint: "/artist/{oid}/cover", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
|   | ||||
| @@ -22,7 +22,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			queries, | ||||
| 			params, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		queries: { | ||||
| @@ -32,7 +32,9 @@ export namespace DataResource { | ||||
| 			name: string, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: string, | ||||
| 		headers?: { | ||||
| 			Range?: string, | ||||
| 		}, | ||||
| 	}): Promise<object> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -42,7 +44,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			queries, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}); | ||||
| 	}; | ||||
| 	/** | ||||
| @@ -52,7 +54,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			queries, | ||||
| 			params, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		queries: { | ||||
| @@ -61,7 +63,9 @@ export namespace DataResource { | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: string, | ||||
| 		headers?: { | ||||
| 			Range: string, | ||||
| 		}, | ||||
| 	}): Promise<object> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -71,7 +75,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			queries, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}); | ||||
| 	}; | ||||
| 	/** | ||||
| @@ -81,7 +85,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			queries, | ||||
| 			params, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		queries: { | ||||
| @@ -90,7 +94,9 @@ export namespace DataResource { | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: string, | ||||
| 		headers?: { | ||||
| 			Range: string, | ||||
| 		}, | ||||
| 	}): Promise<object> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -100,7 +106,7 @@ export namespace DataResource { | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			queries, | ||||
| 			data, | ||||
| 			headers, | ||||
| 		}); | ||||
| 	}; | ||||
| 	/** | ||||
|   | ||||
| @@ -13,8 +13,8 @@ import { | ||||
| import { z as zod } from "zod" | ||||
| import { | ||||
| 	Gender, | ||||
| 	GenderWrite, | ||||
| 	Long, | ||||
| 	GenderCreate, | ||||
| 	GenderUpdate, | ||||
| 	ObjectId, | ||||
| 	ZodGender, | ||||
| 	isGender, | ||||
| @@ -28,12 +28,12 @@ export namespace GenderResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Gender> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/gender/{id}", | ||||
| 				endPoint: "/gender/{oid}", | ||||
| 				requestType: HTTPRequestModel.GET, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| @@ -76,14 +76,14 @@ export namespace GenderResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: GenderWrite, | ||||
| 		data: GenderUpdate, | ||||
| 	}): Promise<Gender> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/gender/{id}", | ||||
| 				requestType: HTTPRequestModel.PATCH, | ||||
| 				endPoint: "/gender/{oid}", | ||||
| 				requestType: HTTPRequestModel.PUT, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| @@ -97,7 +97,7 @@ export namespace GenderResource { | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		data: GenderWrite, | ||||
| 		data: GenderCreate, | ||||
| 	}): Promise<Gender> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -116,12 +116,12 @@ export namespace GenderResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<void> { | ||||
| 		return RESTRequestVoid({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/gender/{id}", | ||||
| 				endPoint: "/gender/{oid}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 			}, | ||||
| @@ -136,12 +136,12 @@ export namespace GenderResource { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			coverId: ObjectId, | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Gender> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/gender/{id}/cover/{coverId}", | ||||
| 				endPoint: "/gender/{oid}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -158,7 +158,7 @@ export namespace GenderResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: { | ||||
| 			file?: File, | ||||
| @@ -168,7 +168,7 @@ export namespace GenderResource { | ||||
| 	}): Promise<Gender> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/gender/{id}/cover", | ||||
| 				endPoint: "/gender/{oid}/cover", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
|   | ||||
| @@ -11,44 +11,23 @@ import { | ||||
|  | ||||
| import { z as zod } from "zod" | ||||
| import { | ||||
| 	Long, | ||||
| 	ObjectId, | ||||
| 	Playlist, | ||||
| 	PlaylistWrite, | ||||
| 	PlaylistCreate, | ||||
| 	PlaylistUpdate, | ||||
| 	ZodPlaylist, | ||||
| 	isPlaylist, | ||||
| } from "../model"; | ||||
|  | ||||
| export namespace PlaylistResource { | ||||
|  | ||||
| 	export function addTrack({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			trackId: Long, | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}/track/{trackId}", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}, isPlaylist); | ||||
| 	}; | ||||
| 	export function get({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			id: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| @@ -89,35 +68,12 @@ export namespace PlaylistResource { | ||||
| 			restConfig, | ||||
| 		}, isGetsTypeReturn); | ||||
| 	}; | ||||
| 	export function patch({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 		data: PlaylistWrite, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}", | ||||
| 				requestType: HTTPRequestModel.PATCH, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isPlaylist); | ||||
| 	}; | ||||
| 	export function post({ | ||||
| 			restConfig, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		data: PlaylistWrite, | ||||
| 		data: PlaylistCreate, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -130,18 +86,41 @@ export namespace PlaylistResource { | ||||
| 			data, | ||||
| 		}, isPlaylist); | ||||
| 	}; | ||||
| 	export function put({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: PlaylistUpdate, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{oid}", | ||||
| 				requestType: HTTPRequestModel.PUT, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isPlaylist); | ||||
| 	}; | ||||
| 	export function remove({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<void> { | ||||
| 		return RESTRequestVoid({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}", | ||||
| 				endPoint: "/playlist/{oid}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 			}, | ||||
| @@ -156,33 +135,12 @@ export namespace PlaylistResource { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			coverId: ObjectId, | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}, isPlaylist); | ||||
| 	}; | ||||
| 	export function removeTrack({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			trackId: Long, | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}/track/{trackId}", | ||||
| 				endPoint: "/playlist/{oid}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -198,7 +156,7 @@ export namespace PlaylistResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: { | ||||
| 			file: File, | ||||
| @@ -206,7 +164,7 @@ export namespace PlaylistResource { | ||||
| 	}): Promise<Playlist> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/playlist/{id}/cover", | ||||
| 				endPoint: "/playlist/{oid}/cover", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
|   | ||||
| @@ -15,46 +15,26 @@ import { | ||||
| 	Long, | ||||
| 	ObjectId, | ||||
| 	Track, | ||||
| 	TrackWrite, | ||||
| 	TrackCreate, | ||||
| 	TrackUpdate, | ||||
| 	ZodTrack, | ||||
| 	isTrack, | ||||
| } from "../model"; | ||||
|  | ||||
| export namespace TrackResource { | ||||
|  | ||||
| 	export function addTrack({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			artistId: Long, | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}/artist/{artistId}", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}, isTrack); | ||||
| 	}; | ||||
| 	export function get({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}", | ||||
| 				endPoint: "/track/{oid}", | ||||
| 				requestType: HTTPRequestModel.GET, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| @@ -90,35 +70,12 @@ export namespace TrackResource { | ||||
| 			restConfig, | ||||
| 		}, isGetsTypeReturn); | ||||
| 	}; | ||||
| 	export function patch({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 		data: TrackWrite, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}", | ||||
| 				requestType: HTTPRequestModel.PATCH, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isTrack); | ||||
| 	}; | ||||
| 	export function post({ | ||||
| 			restConfig, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		data: TrackWrite, | ||||
| 		data: TrackCreate, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| @@ -131,18 +88,41 @@ export namespace TrackResource { | ||||
| 			data, | ||||
| 		}, isTrack); | ||||
| 	}; | ||||
| 	export function put({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: TrackUpdate, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{oid}", | ||||
| 				requestType: HTTPRequestModel.PUT, | ||||
| 				contentType: HTTPMimeType.JSON, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 			data, | ||||
| 		}, isTrack); | ||||
| 	}; | ||||
| 	export function remove({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<void> { | ||||
| 		return RESTRequestVoid({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}", | ||||
| 				endPoint: "/track/{oid}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 			}, | ||||
| @@ -157,33 +137,12 @@ export namespace TrackResource { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			coverId: ObjectId, | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| 			}, | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}, isTrack); | ||||
| 	}; | ||||
| 	export function removeTrack({ | ||||
| 			restConfig, | ||||
| 			params, | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			artistId: Long, | ||||
| 			id: Long, | ||||
| 		}, | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}/artist/{trackId}", | ||||
| 				endPoint: "/track/{oid}/cover/{coverId}", | ||||
| 				requestType: HTTPRequestModel.DELETE, | ||||
| 				contentType: HTTPMimeType.TEXT_PLAIN, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -200,7 +159,7 @@ export namespace TrackResource { | ||||
| 		}: { | ||||
| 		restConfig: RESTConfig, | ||||
| 		params: { | ||||
| 			id: Long, | ||||
| 			oid: ObjectId, | ||||
| 		}, | ||||
| 		data: { | ||||
| 			file: File, | ||||
| @@ -210,7 +169,7 @@ export namespace TrackResource { | ||||
| 	}): Promise<Track> { | ||||
| 		return RESTRequestJson({ | ||||
| 			restModel: { | ||||
| 				endPoint: "/track/{id}/cover", | ||||
| 				endPoint: "/track/{oid}/cover", | ||||
| 				requestType: HTTPRequestModel.POST, | ||||
| 				contentType: HTTPMimeType.MULTIPART, | ||||
| 				accept: HTTPMimeType.JSON, | ||||
| @@ -230,9 +189,9 @@ export namespace TrackResource { | ||||
| 		data: { | ||||
| 			file: File, | ||||
| 			trackId?: Long, | ||||
| 			genderId?: Long, | ||||
| 			albumId?: Long, | ||||
| 			artistId?: Long, | ||||
| 			genderId?: ObjectId, | ||||
| 			albumId?: ObjectId, | ||||
| 			artistId?: ObjectId, | ||||
| 			title: string, | ||||
| 		}, | ||||
| 		callbacks?: RESTCallbacks, | ||||
|   | ||||
| @@ -3,18 +3,18 @@ | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodIsoDate} from "./iso-date"; | ||||
| import {ZodObjectId} from "./object-id"; | ||||
| import {ZodLocalDate} from "./local-date"; | ||||
| import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; | ||||
| import {ZodOIDGenericDataSoftDelete, ZodOIDGenericDataSoftDeleteUpdate , ZodOIDGenericDataSoftDeleteCreate } from "./oid-generic-data-soft-delete"; | ||||
|  | ||||
| export const ZodAlbum = ZodGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().max(256).optional(), | ||||
| 	description: zod.string().optional(), | ||||
| export const ZodAlbum = ZodOIDGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().min(1).max(256).optional(), | ||||
| 	description: zod.string().max(8192).optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).optional(), | ||||
| 	publication: ZodLocalDate.optional(), | ||||
| 	covers: zod.array(ZodObjectId).readonly().optional(), | ||||
| 	publication: ZodIsoDate.optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| @@ -29,25 +29,39 @@ export function isAlbum(data: any): data is Album { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodAlbumWrite = ZodGenericDataSoftDeleteWrite.extend({ | ||||
| 	name: zod.string().max(256).nullable().optional(), | ||||
| 	description: zod.string().nullable().optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).nullable().optional(), | ||||
| 	publication: ZodLocalDate.nullable().optional(), | ||||
| export const ZodAlbumUpdate = ZodOIDGenericDataSoftDeleteUpdate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
| 	publication: ZodIsoDate.nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type AlbumWrite = zod.infer<typeof ZodAlbumWrite>; | ||||
| export type AlbumUpdate = zod.infer<typeof ZodAlbumUpdate>; | ||||
|  | ||||
| export function isAlbumWrite(data: any): data is AlbumWrite { | ||||
| export function isAlbumUpdate(data: any): data is AlbumUpdate { | ||||
| 	try { | ||||
| 		ZodAlbumWrite.parse(data); | ||||
| 		ZodAlbumUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodAlbumWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodAlbumUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodAlbumCreate = ZodOIDGenericDataSoftDeleteCreate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
| 	publication: ZodIsoDate.nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type AlbumCreate = zod.infer<typeof ZodAlbumCreate>; | ||||
|  | ||||
| export function isAlbumCreate(data: any): data is AlbumCreate { | ||||
| 	try { | ||||
| 		ZodAlbumCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodAlbumCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,21 +3,21 @@ | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodIsoDate} from "./iso-date"; | ||||
| import {ZodObjectId} from "./object-id"; | ||||
| import {ZodLocalDate} from "./local-date"; | ||||
| import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; | ||||
| import {ZodOIDGenericDataSoftDelete, ZodOIDGenericDataSoftDeleteUpdate , ZodOIDGenericDataSoftDeleteCreate } from "./oid-generic-data-soft-delete"; | ||||
|  | ||||
| export const ZodArtist = ZodGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().max(256).optional(), | ||||
| 	description: zod.string().optional(), | ||||
| export const ZodArtist = ZodOIDGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().min(1).max(256).optional(), | ||||
| 	description: zod.string().max(8192).optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).optional(), | ||||
| 	firstName: zod.string().max(256).optional(), | ||||
| 	surname: zod.string().max(256).optional(), | ||||
| 	birth: ZodLocalDate.optional(), | ||||
| 	death: ZodLocalDate.optional(), | ||||
| 	covers: zod.array(ZodObjectId).readonly().optional(), | ||||
| 	firstName: zod.string().min(1).max(256).optional(), | ||||
| 	surname: zod.string().min(1).max(256).optional(), | ||||
| 	birth: ZodIsoDate.optional(), | ||||
| 	death: ZodIsoDate.optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| @@ -32,28 +32,45 @@ export function isArtist(data: any): data is Artist { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodArtistWrite = ZodGenericDataSoftDeleteWrite.extend({ | ||||
| 	name: zod.string().max(256).nullable().optional(), | ||||
| 	description: zod.string().nullable().optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).nullable().optional(), | ||||
| 	firstName: zod.string().max(256).nullable().optional(), | ||||
| 	surname: zod.string().max(256).nullable().optional(), | ||||
| 	birth: ZodLocalDate.nullable().optional(), | ||||
| 	death: ZodLocalDate.nullable().optional(), | ||||
| export const ZodArtistUpdate = ZodOIDGenericDataSoftDeleteUpdate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
| 	firstName: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	surname: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	birth: ZodIsoDate.nullable().optional(), | ||||
| 	death: ZodIsoDate.nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type ArtistWrite = zod.infer<typeof ZodArtistWrite>; | ||||
| export type ArtistUpdate = zod.infer<typeof ZodArtistUpdate>; | ||||
|  | ||||
| export function isArtistWrite(data: any): data is ArtistWrite { | ||||
| export function isArtistUpdate(data: any): data is ArtistUpdate { | ||||
| 	try { | ||||
| 		ZodArtistWrite.parse(data); | ||||
| 		ZodArtistUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodArtistWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodArtistUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodArtistCreate = ZodOIDGenericDataSoftDeleteCreate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
| 	firstName: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	surname: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	birth: ZodIsoDate.nullable().optional(), | ||||
| 	death: ZodIsoDate.nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type ArtistCreate = zod.infer<typeof ZodArtistCreate>; | ||||
|  | ||||
| export function isArtistCreate(data: any): data is ArtistCreate { | ||||
| 	try { | ||||
| 		ZodArtistCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodArtistCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -4,15 +4,15 @@ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodObjectId} from "./object-id"; | ||||
| import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; | ||||
| import {ZodOIDGenericDataSoftDelete, ZodOIDGenericDataSoftDeleteUpdate , ZodOIDGenericDataSoftDeleteCreate } from "./oid-generic-data-soft-delete"; | ||||
|  | ||||
| export const ZodGender = ZodGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().max(256).optional(), | ||||
| 	description: zod.string().optional(), | ||||
| export const ZodGender = ZodOIDGenericDataSoftDelete.extend({ | ||||
| 	name: zod.string().min(1).max(256).optional(), | ||||
| 	description: zod.string().max(8192).optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).optional(), | ||||
| 	covers: zod.array(ZodObjectId).readonly().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| @@ -27,24 +27,37 @@ export function isGender(data: any): data is Gender { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenderWrite = ZodGenericDataSoftDeleteWrite.extend({ | ||||
| 	name: zod.string().max(256).nullable().optional(), | ||||
| 	description: zod.string().nullable().optional(), | ||||
| 	/** | ||||
| 	 * List of Id of the specific covers | ||||
| 	 */ | ||||
| 	covers: zod.array(ZodObjectId).nullable().optional(), | ||||
| export const ZodGenderUpdate = ZodOIDGenericDataSoftDeleteUpdate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type GenderWrite = zod.infer<typeof ZodGenderWrite>; | ||||
| export type GenderUpdate = zod.infer<typeof ZodGenderUpdate>; | ||||
|  | ||||
| export function isGenderWrite(data: any): data is GenderWrite { | ||||
| export function isGenderUpdate(data: any): data is GenderUpdate { | ||||
| 	try { | ||||
| 		ZodGenderWrite.parse(data); | ||||
| 		ZodGenderUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenderWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodGenderUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenderCreate = ZodOIDGenericDataSoftDeleteCreate.extend({ | ||||
| 	name: zod.string().min(1).max(256).nullable().optional(), | ||||
| 	description: zod.string().max(8192).nullable().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type GenderCreate = zod.infer<typeof ZodGenderCreate>; | ||||
|  | ||||
| export function isGenderCreate(data: any): data is GenderCreate { | ||||
| 	try { | ||||
| 		ZodGenderCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenderCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodGenericData, ZodGenericDataWrite } from "./generic-data"; | ||||
| import {ZodGenericData, ZodGenericDataUpdate , ZodGenericDataCreate } from "./generic-data"; | ||||
|  | ||||
| export const ZodGenericDataSoftDelete = ZodGenericData.extend({ | ||||
| 	/** | ||||
| @@ -24,18 +24,29 @@ export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelet | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericDataSoftDeleteWrite = ZodGenericDataWrite.extend({ | ||||
| export const ZodGenericDataSoftDeleteUpdate = ZodGenericDataUpdate; | ||||
|  | ||||
| }); | ||||
| export type GenericDataSoftDeleteUpdate = zod.infer<typeof ZodGenericDataSoftDeleteUpdate>; | ||||
|  | ||||
| export type GenericDataSoftDeleteWrite = zod.infer<typeof ZodGenericDataSoftDeleteWrite>; | ||||
|  | ||||
| export function isGenericDataSoftDeleteWrite(data: any): data is GenericDataSoftDeleteWrite { | ||||
| export function isGenericDataSoftDeleteUpdate(data: any): data is GenericDataSoftDeleteUpdate { | ||||
| 	try { | ||||
| 		ZodGenericDataSoftDeleteWrite.parse(data); | ||||
| 		ZodGenericDataSoftDeleteUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataSoftDeleteWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataSoftDeleteUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericDataSoftDeleteCreate = ZodGenericDataCreate; | ||||
|  | ||||
| export type GenericDataSoftDeleteCreate = zod.infer<typeof ZodGenericDataSoftDeleteCreate>; | ||||
|  | ||||
| export function isGenericDataSoftDeleteCreate(data: any): data is GenericDataSoftDeleteCreate { | ||||
| 	try { | ||||
| 		ZodGenericDataSoftDeleteCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataSoftDeleteCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,8 +3,8 @@ | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing"; | ||||
| import {ZodLong} from "./long"; | ||||
| import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing"; | ||||
|  | ||||
| export const ZodGenericData = ZodGenericTiming.extend({ | ||||
| 	/** | ||||
| @@ -25,18 +25,29 @@ export function isGenericData(data: any): data is GenericData { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericDataWrite = ZodGenericTimingWrite.extend({ | ||||
| export const ZodGenericDataUpdate = ZodGenericTimingUpdate; | ||||
|  | ||||
| }); | ||||
| export type GenericDataUpdate = zod.infer<typeof ZodGenericDataUpdate>; | ||||
|  | ||||
| export type GenericDataWrite = zod.infer<typeof ZodGenericDataWrite>; | ||||
|  | ||||
| export function isGenericDataWrite(data: any): data is GenericDataWrite { | ||||
| export function isGenericDataUpdate(data: any): data is GenericDataUpdate { | ||||
| 	try { | ||||
| 		ZodGenericDataWrite.parse(data); | ||||
| 		ZodGenericDataUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericDataCreate = ZodGenericTimingCreate; | ||||
|  | ||||
| export type GenericDataCreate = zod.infer<typeof ZodGenericDataCreate>; | ||||
|  | ||||
| export function isGenericDataCreate(data: any): data is GenericDataCreate { | ||||
| 	try { | ||||
| 		ZodGenericDataCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericDataCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -28,18 +28,33 @@ export function isGenericTiming(data: any): data is GenericTiming { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericTimingWrite = zod.object({ | ||||
| export const ZodGenericTimingUpdate = zod.object({ | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type GenericTimingWrite = zod.infer<typeof ZodGenericTimingWrite>; | ||||
| export type GenericTimingUpdate = zod.infer<typeof ZodGenericTimingUpdate>; | ||||
|  | ||||
| export function isGenericTimingWrite(data: any): data is GenericTimingWrite { | ||||
| export function isGenericTimingUpdate(data: any): data is GenericTimingUpdate { | ||||
| 	try { | ||||
| 		ZodGenericTimingWrite.parse(data); | ||||
| 		ZodGenericTimingUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericTimingWrite' error=${e}`); | ||||
| 		console.log(`Fail to parse data type='ZodGenericTimingUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodGenericTimingCreate = zod.object({ | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type GenericTimingCreate = zod.infer<typeof ZodGenericTimingCreate>; | ||||
|  | ||||
| export function isGenericTimingCreate(data: any): data is GenericTimingCreate { | ||||
| 	try { | ||||
| 		ZodGenericTimingCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodGenericTimingCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -19,18 +19,3 @@ export function isHealthResult(data: any): data is HealthResult { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodHealthResultWrite = zod.object({ | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type HealthResultWrite = zod.infer<typeof ZodHealthResultWrite>; | ||||
|  | ||||
| export function isHealthResultWrite(data: any): data is HealthResultWrite { | ||||
| 	try { | ||||
| 		ZodHealthResultWrite.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodHealthResultWrite' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -10,15 +10,20 @@ export * from "./generic-timing" | ||||
| export * from "./health-result" | ||||
| export * from "./integer" | ||||
| export * from "./iso-date" | ||||
| export * from "./local-date" | ||||
| export * from "./jwt-header" | ||||
| export * from "./jwt-payload" | ||||
| export * from "./jwt-token" | ||||
| export * from "./long" | ||||
| export * from "./object-id" | ||||
| export * from "./oid-generic-data" | ||||
| export * from "./oid-generic-data-soft-delete" | ||||
| export * from "./part-right" | ||||
| export * from "./part-right" | ||||
| export * from "./playlist" | ||||
| export * from "./rest-error-response" | ||||
| export * from "./rest-input-error" | ||||
| export * from "./timestamp" | ||||
| export * from "./track" | ||||
| export * from "./user" | ||||
| export * from "./user-karusic" | ||||
| export * from "./user-me" | ||||
| export * from "./uuid" | ||||
|   | ||||
							
								
								
									
										23
									
								
								front/src/back-api/model/jwt-header.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								front/src/back-api/model/jwt-header.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| /** | ||||
|  * Interface of the server (auto-generated code) | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
|  | ||||
| export const ZodJwtHeader = zod.object({ | ||||
| 	typ: zod.string().max(128), | ||||
| 	alg: zod.string().max(128), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type JwtHeader = zod.infer<typeof ZodJwtHeader>; | ||||
|  | ||||
| export function isJwtHeader(data: any): data is JwtHeader { | ||||
| 	try { | ||||
| 		ZodJwtHeader.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodJwtHeader' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										29
									
								
								front/src/back-api/model/jwt-payload.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								front/src/back-api/model/jwt-payload.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /** | ||||
|  * Interface of the server (auto-generated code) | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodLong} from "./long"; | ||||
|  | ||||
| export const ZodJwtPayload = zod.object({ | ||||
| 	sub: zod.string(), | ||||
| 	application: zod.string(), | ||||
| 	iss: zod.string(), | ||||
| 	right: zod.record(zod.string(), zod.record(zod.string(), ZodLong)), | ||||
| 	login: zod.string(), | ||||
| 	exp: ZodLong, | ||||
| 	iat: ZodLong, | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type JwtPayload = zod.infer<typeof ZodJwtPayload>; | ||||
|  | ||||
| export function isJwtPayload(data: any): data is JwtPayload { | ||||
| 	try { | ||||
| 		ZodJwtPayload.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodJwtPayload' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										26
									
								
								front/src/back-api/model/jwt-token.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								front/src/back-api/model/jwt-token.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| /** | ||||
|  * Interface of the server (auto-generated code) | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodJwtHeader} from "./jwt-header"; | ||||
| import {ZodJwtPayload} from "./jwt-payload"; | ||||
|  | ||||
| export const ZodJwtToken = zod.object({ | ||||
| 	header: ZodJwtHeader, | ||||
| 	payload: ZodJwtPayload, | ||||
| 	signature: zod.string(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type JwtToken = zod.infer<typeof ZodJwtToken>; | ||||
|  | ||||
| export function isJwtToken(data: any): data is JwtToken { | ||||
| 	try { | ||||
| 		ZodJwtToken.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodJwtToken' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										52
									
								
								front/src/back-api/model/oid-generic-data-soft-delete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								front/src/back-api/model/oid-generic-data-soft-delete.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /** | ||||
|  * Interface of the server (auto-generated code) | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodOIDGenericData, ZodOIDGenericDataUpdate , ZodOIDGenericDataCreate } from "./oid-generic-data"; | ||||
|  | ||||
| export const ZodOIDGenericDataSoftDelete = ZodOIDGenericData.extend({ | ||||
| 	/** | ||||
| 	 * Deleted state | ||||
| 	 */ | ||||
| 	deleted: zod.boolean().readonly().optional(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type OIDGenericDataSoftDelete = zod.infer<typeof ZodOIDGenericDataSoftDelete>; | ||||
|  | ||||
| export function isOIDGenericDataSoftDelete(data: any): data is OIDGenericDataSoftDelete { | ||||
| 	try { | ||||
| 		ZodOIDGenericDataSoftDelete.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericDataSoftDelete' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodOIDGenericDataSoftDeleteUpdate = ZodOIDGenericDataUpdate; | ||||
|  | ||||
| export type OIDGenericDataSoftDeleteUpdate = zod.infer<typeof ZodOIDGenericDataSoftDeleteUpdate>; | ||||
|  | ||||
| export function isOIDGenericDataSoftDeleteUpdate(data: any): data is OIDGenericDataSoftDeleteUpdate { | ||||
| 	try { | ||||
| 		ZodOIDGenericDataSoftDeleteUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericDataSoftDeleteUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodOIDGenericDataSoftDeleteCreate = ZodOIDGenericDataCreate; | ||||
|  | ||||
| export type OIDGenericDataSoftDeleteCreate = zod.infer<typeof ZodOIDGenericDataSoftDeleteCreate>; | ||||
|  | ||||
| export function isOIDGenericDataSoftDeleteCreate(data: any): data is OIDGenericDataSoftDeleteCreate { | ||||
| 	try { | ||||
| 		ZodOIDGenericDataSoftDeleteCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericDataSoftDeleteCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										53
									
								
								front/src/back-api/model/oid-generic-data.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								front/src/back-api/model/oid-generic-data.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /** | ||||
|  * Interface of the server (auto-generated code) | ||||
|  */ | ||||
| import { z as zod } from "zod"; | ||||
|  | ||||
| import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing"; | ||||
| import {ZodObjectId} from "./object-id"; | ||||
|  | ||||
| export const ZodOIDGenericData = ZodGenericTiming.extend({ | ||||
| 	/** | ||||
| 	 * Unique ObjectID of the object | ||||
| 	 */ | ||||
| 	oid: ZodObjectId.readonly(), | ||||
|  | ||||
| }); | ||||
|  | ||||
| export type OIDGenericData = zod.infer<typeof ZodOIDGenericData>; | ||||
|  | ||||
| export function isOIDGenericData(data: any): data is OIDGenericData { | ||||
| 	try { | ||||
| 		ZodOIDGenericData.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericData' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodOIDGenericDataUpdate = ZodGenericTimingUpdate; | ||||
|  | ||||
| export type OIDGenericDataUpdate = zod.infer<typeof ZodOIDGenericDataUpdate>; | ||||
|  | ||||
| export function isOIDGenericDataUpdate(data: any): data is OIDGenericDataUpdate { | ||||
| 	try { | ||||
| 		ZodOIDGenericDataUpdate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericDataUpdate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| export const ZodOIDGenericDataCreate = ZodGenericTimingCreate; | ||||
|  | ||||
| export type OIDGenericDataCreate = zod.infer<typeof ZodOIDGenericDataCreate>; | ||||
|  | ||||
| export function isOIDGenericDataCreate(data: any): data is OIDGenericDataCreate { | ||||
| 	try { | ||||
| 		ZodOIDGenericDataCreate.parse(data); | ||||
| 		return true; | ||||
| 	} catch (e: any) { | ||||
| 		console.log(`Fail to parse data type='ZodOIDGenericDataCreate' error=${e}`); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| @@ -6,6 +6,7 @@ import { z as zod } from "zod"; | ||||
|  | ||||
| export enum PartRight  { | ||||
| 	READ = 1, | ||||
| 	NONE = 0, | ||||
| 	WRITE = 2, | ||||
| 	READ_WRITE = 3, | ||||
| 	}; | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user