Compare commits
	
		
			62 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ba0ab6d57b | ||
|   | ef17ad203d | ||
|   | 19f08d36cf | ||
|   | 141c8f1659 | ||
|   | dd677afff0 | ||
|   | cc0d502229 | ||
|   | 0d32740ec7 | ||
|   | 839236ecd1 | ||
|   | 4c7a9e27e3 | ||
|   | 08879a6860 | ||
|   | f72645e05c | ||
|   | e834e0f096 | ||
|   | 4eca38ad24 | ||
|   | 7543f07562 | ||
|   | a90be58013 | ||
|   | 93a643d10d | ||
|   | 85c52fac2a | ||
|   | 8239e387fb | ||
|   | b4e17d6853 | ||
|   | ca16e3c43a | ||
|   | 5f9247391a | ||
|   | ee12030cf6 | ||
|   | b062fb0b97 | ||
|   | 01c72af17a | ||
|   | b28eb6d3b7 | ||
|   | 5d2392ad9e | ||
|   | efb334f8de | ||
|   | d4b1c6a9e1 | ||
|   | f7a62560c7 | ||
|   | e7393c0192 | ||
|   | bc647ce9be | ||
|   | af6cb7d1ec | ||
|   | a88e7d2ce5 | ||
| 3d78b90ff1 | |||
| 3d7ee42ca8 | |||
| 77acd2060b | |||
| 88f65f0806 | |||
| 6df71e3341 | |||
| 263a4ae4c0 | |||
| 57a48de52f | |||
| ae9f00a60a | |||
| 93b95becb7 | |||
| bd66703a08 | |||
| 86fec254aa | |||
| 6f16bffe31 | |||
| 1fc1b5d35d | |||
| 7d6e3bb8c8 | |||
| 11b8b575e4 | |||
| dfa245e842 | |||
| ed94562372 | |||
| 5fee3a1390 | |||
| 96bc7ec052 | |||
| 94d2fd0fc8 | |||
| d8ceaef3f9 | |||
| 334d68ac1f | |||
| e4831e1a17 | |||
| e0b81d2122 | |||
| 95c3c0f968 | |||
| 154c825499 | |||
| 5e8b244ebd | |||
| 48ad545da1 | |||
| 4b002aaee4 | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -53,6 +53,8 @@ testem.log | |||||||
| # System Files | # System Files | ||||||
| .DS_Store | .DS_Store | ||||||
| Thumbs.db | Thumbs.db | ||||||
|  | /env_dev/data | ||||||
|  | /env_dev/dataMongo | ||||||
|  |  | ||||||
| backPY/env | backPY/env | ||||||
|  |  | ||||||
| @@ -62,3 +64,5 @@ __pycache__ | |||||||
|  |  | ||||||
| .design/ | .design/ | ||||||
| .vscode/ | .vscode/ | ||||||
|  | front/storybook-static | ||||||
|  | back/bin | ||||||
|   | |||||||
| @@ -1,7 +1,32 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
|  |  | ||||||
|  | version_file="../version.txt" | ||||||
|  |  | ||||||
|  | # update new release dependency | ||||||
| cd back | cd back | ||||||
| mvn versions:set -DnewVersion=$(cat ../version.txt) | # update the Maven version number | ||||||
|  | mvn versions:set -DnewVersion=$(sed 's/dev/SNAPSHOT/g' $version_file) | ||||||
|  | if grep -q "DEV" "$version_file"; then | ||||||
|  |     # update all versions release of dependency | ||||||
|  |     mvn versions:use-latest-releases  | ||||||
|  |     # update our manage dependency as snapshoot | ||||||
|  |     mvn versions:use-latest-versions -Dincludes=kangaroo-and-rabbit | ||||||
|  | else | ||||||
|  |     # update our manage dependency as release (must be done before) | ||||||
|  |     mvn versions:use-latest-releases -Dincludes=kangaroo-and-rabbit | ||||||
|  | fi | ||||||
| cd - | cd - | ||||||
|  |  | ||||||
|  |  | ||||||
|  | cd front | ||||||
|  | if grep -q "dev" "$version_file"; then | ||||||
|  |     # update all dependency | ||||||
|  |     pnpm install | ||||||
|  |     pnpm run update_packages | ||||||
|  | else | ||||||
|  |     # in case of release ==> can not do it automatically ... | ||||||
|  |     echo not implemented | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | cd - | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,25 +1,33 @@ | |||||||
| ###################################################################################### | ###################################################################################### | ||||||
| ## | ## | ||||||
| ## buyilding-end install applications: | ## building-end install applications: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM archlinux:base-devel AS builder | FROM archlinux:base-devel AS common | ||||||
| # update system | # update system | ||||||
| RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | ||||||
|     && pacman -S --noconfirm jdk-openjdk maven npm \ |     && pacman -S --noconfirm jdk-openjdk wget\ | ||||||
|     && pacman -Scc --noconfirm |     && pacman -Scc --noconfirm | ||||||
|  |  | ||||||
| ENV PATH /tmp/node_modules/.bin:$PATH |  | ||||||
| WORKDIR /tmp | WORKDIR /tmp | ||||||
|  |  | ||||||
|  | FROM common AS builder | ||||||
|  | # update system | ||||||
|  | RUN pacman -Syu --noconfirm && pacman-db-upgrade \ | ||||||
|  |     && pacman -S --noconfirm maven npm pnpm \ | ||||||
|  |     && pacman -Scc --noconfirm | ||||||
|  |  | ||||||
|  | ENV PATH=/tmp/node_modules/.bin:$PATH | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| ## | ## | ||||||
| ## Build back: | ## Build back: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM builder AS buildBack | FROM builder AS build_back | ||||||
| COPY back/pom.xml /tmp | COPY back/pom.xml ./ | ||||||
| COPY back/src /tmp/src/ | COPY back/Formatter.xml ./ | ||||||
|  | COPY back/src ./src/ | ||||||
| RUN mvn clean compile assembly:single | RUN mvn clean compile assembly:single | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| @@ -27,26 +35,44 @@ RUN mvn clean compile assembly:single | |||||||
| ## Build front: | ## Build front: | ||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| FROM builder AS buildFront | FROM builder AS dependency_front | ||||||
|  |  | ||||||
| ADD front/package-lock.json \ | RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc | ||||||
|     front/package.json \ |  | ||||||
|     front/karma.conf.js \ | COPY front/package.json \ | ||||||
|     front/protractor.conf.js \ |     front/pnpm-lock.yaml \ | ||||||
|     /tmp/ |     ./ | ||||||
|  | COPY front/src/theme ./src/theme | ||||||
|  |  | ||||||
| # install and cache app dependencies | # install and cache app dependencies | ||||||
| RUN npm install | RUN pnpm install --prod=false | ||||||
|  |  | ||||||
| ADD front/e2e \ | ############################################################### | ||||||
|     front/tsconfig.json \ | ## Install sources | ||||||
|     front/tslint.json \ | ############################################################### | ||||||
|     front/angular.json \ | FROM dependency_front AS load_sources_front | ||||||
|     /tmp/ |  | ||||||
| ADD front/src /tmp/src |  | ||||||
|  |  | ||||||
| # generate build | # JUST to get the version of the application and his sha... | ||||||
| RUN ng build --output-path=dist --configuration=production --base-href=/karideo/ --deploy-url=/karideo/  | COPY \ | ||||||
|  |   front/tsconfig.json \ | ||||||
|  |   front/tsconfig.node.json \ | ||||||
|  |   front/vite.config.mts \ | ||||||
|  |   front/index.html \ | ||||||
|  |   ./ | ||||||
|  |  | ||||||
|  | COPY front/public ./public | ||||||
|  | COPY front/src ./src | ||||||
|  |  | ||||||
|  | # We are not in prod mode ==> we need to overwrite the production env. | ||||||
|  | ARG env=front/.env.production | ||||||
|  | COPY ${env} .env | ||||||
|  |  | ||||||
|  | ############################################################### | ||||||
|  | ## Build the sources | ||||||
|  | ############################################################### | ||||||
|  | FROM load_sources_front AS build_front | ||||||
|  | # build in bundle mode all the application | ||||||
|  | RUN pnpm static:build | ||||||
|  |  | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
| ## | ## | ||||||
| @@ -54,26 +80,24 @@ RUN ng build --output-path=dist --configuration=production --base-href=/karideo/ | |||||||
| ## | ## | ||||||
| ###################################################################################### | ###################################################################################### | ||||||
|  |  | ||||||
| FROM bellsoft/liberica-openjdk-alpine:latest | FROM bellsoft/liberica-openjdk-alpine-musl:latest | ||||||
| # add wget to manage the health check... |  | ||||||
| RUN apk add --no-cache wget |  | ||||||
|  |  | ||||||
| #FROM archlinux:base | RUN apk add --no-cache wget \ | ||||||
| #RUN pacman -Syu --noconfirm && pacman-db-upgrade |   && addgroup -g 1000 user \ | ||||||
| ## install package |   && adduser --system -u 1000 -G user user | ||||||
| #RUN pacman -S --noconfirm jdk-openjdk wget |  | ||||||
| ## intall npm |  | ||||||
| #RUN pacman -S --noconfirm npm |  | ||||||
| ## clean all the caches Need only on the release environment |  | ||||||
| #RUN pacman -Scc --noconfirm |  | ||||||
|  |  | ||||||
| ENV LANG=C.UTF-8 | ENV LANG=C.UTF-8 | ||||||
|  |  | ||||||
| COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar |  | ||||||
| COPY --from=buildFront /tmp/dist /application/front/ |  | ||||||
|  |  | ||||||
| WORKDIR /application/ |  | ||||||
|  |  | ||||||
| EXPOSE 80 | EXPOSE 80 | ||||||
|  | WORKDIR /application/ | ||||||
|  | RUN chown user:user -R /application | ||||||
|  |  | ||||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karideo.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", "-Xms128M", "-Xmx1G", "-cp", "/application/application.jar", "org.atriasoft.karideo.WebLauncher"] | ||||||
|  |  | ||||||
|  | COPY --chown=user:user --from=build_back /tmp/out/maven/*.jar /application/application.jar | ||||||
|  | COPY --chown=user:user --from=build_front /tmp/dist /application/front/ | ||||||
|  |  | ||||||
|  | USER user | ||||||
|   | |||||||
							
								
								
									
										145
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | |||||||
|  | Karideo | ||||||
|  | ======= | ||||||
|  |  | ||||||
|  | **K**angaroo **A**nd **R**abbit (v)ideo is a simple framework to propose video streaming for personal network | ||||||
|  |  | ||||||
|  | Run in local: | ||||||
|  | ============= | ||||||
|  |  | ||||||
|  | Start tools | ||||||
|  | ----------- | ||||||
|  |  | ||||||
|  | Start the server basic interfaces: (DB(mySQL), Adminer) | ||||||
|  |  | ||||||
|  | ```{.bash} | ||||||
|  | # start the Bdd interface (no big data > 50Mo) | ||||||
|  | docker compose -f env_dev/docker-compose.yaml up -d | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Start the Back-end: | ||||||
|  | ------------------- | ||||||
|  |  | ||||||
|  | backend is developed in JAVA | ||||||
|  |  | ||||||
|  | The first step is configuring your JAVA version (or select the JVM with the OS) | ||||||
|  | ```bash | ||||||
|  | export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 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 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 | ||||||
|  | ======================== | ||||||
|  |  | ||||||
|  | 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.karideo** | **org.kar.archidata** | **other** | | ||||||
|  | | ----------------- | ------------------- | --------------------- | --------- | | ||||||
|  | | `prod`            | INFO                | INFO                  | INFO      | | ||||||
|  | | `prod-debug`      | DEBUG               | INFO                  | INFO      | | ||||||
|  | | `prod-trace`      | TRACE               | DEBUG                 | INFO      | | ||||||
|  | | `prod-trace-full` | TRACE               | TRACE                 | INFO      | | ||||||
|  | | `dev`             | TRACE               | DEBUG                 | INFO      | | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Manual set in production: | ||||||
|  | ========================= | ||||||
|  |  | ||||||
|  | Connect on the registry | ||||||
|  | ------------------------ | ||||||
|  |  | ||||||
|  | To log-in and log-out from the registry: | ||||||
|  | ```bash | ||||||
|  | export REGISTRY_ADDRESS=gitea.atria-soft.org | ||||||
|  | docker login -u <<YOUR_USER_NAME>> ${REGISTRY_ADDRESS} | ||||||
|  | docker logout ${REGISTRY_ADDRESS} | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | pull the root image of dockers | ||||||
|  | ------------------------------ | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | docker pull archlinux:base-devel | ||||||
|  | docker pull bellsoft/liberica-openjdk-alpine:latest | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Deploy on mongodb | ||||||
|  | ----------------- | ||||||
|  |  | ||||||
|  | connect on the mongosh interface: | ||||||
|  | ```bash | ||||||
|  | docker compose exec kar_mongodb_service mongosh -u root | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Create the base and the user | ||||||
|  | ``` | ||||||
|  | use karideo | ||||||
|  | db.createUser({ | ||||||
|  |   user: "karideo", | ||||||
|  |   pwd: "your_password", | ||||||
|  |   roles: [ | ||||||
|  |     { role: "readWrite", db: "karideo" } | ||||||
|  |   ] | ||||||
|  | }) | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Create the version | ||||||
|  | ------------------ | ||||||
|  |  | ||||||
|  | Execute in the local folder: (use ```dev``` for development and ```latest``` for production release) | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | export TAG_DOCKER=latest | ||||||
|  | export REGISTRY_ADDRESS=gitea.atria-soft.org | ||||||
|  | docker build -t ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karideo:${TAG_DOCKER} . | ||||||
|  | docker push ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karideo:${TAG_DOCKER} | ||||||
|  | ``` | ||||||
| @@ -53,6 +53,9 @@ Checkstyle configuration that checks the sun coding conventions. | |||||||
|     <module name="LambdaParameterName"/> |     <module name="LambdaParameterName"/> | ||||||
|     <module name="Regexp"/> |     <module name="Regexp"/> | ||||||
|     <module name="RegexpSinglelineJava"/> |     <module name="RegexpSinglelineJava"/> | ||||||
|  |     <module name="UnusedPrivateField"> | ||||||
|  |         <property name="ignorePattern" value="LOGGER"/> | ||||||
|  |     </module> | ||||||
|   </module> |   </module> | ||||||
|   <module name="BeforeExecutionExclusionFileFilter"> |   <module name="BeforeExecutionExclusionFileFilter"> | ||||||
|     <property name="fileNamePattern" value="module\-info\.java$"/> |     <property name="fileNamePattern" value="module\-info\.java$"/> | ||||||
|   | |||||||
| @@ -1,21 +0,0 @@ | |||||||
| FROM maven:3.6.3-openjdk-16 AS build |  | ||||||
|  |  | ||||||
| COPY pom.xml /tmp/ |  | ||||||
| COPY src /tmp/src/ |  | ||||||
| WORKDIR /tmp/ |  | ||||||
| RUN mvn clean compile assembly:single |  | ||||||
|  |  | ||||||
| FROM bellsoft/liberica-openjdk-alpine:latest |  | ||||||
| ENV LANG=C.UTF-8 |  | ||||||
|  |  | ||||||
| # add wget to manage the health check... |  | ||||||
| RUN apk add --no-cache wget |  | ||||||
|  |  | ||||||
| RUN mkdir /application/ |  | ||||||
| COPY --from=build /tmp/out/maven/*.jar /application/application.jar |  | ||||||
| WORKDIR /application/ |  | ||||||
|  |  | ||||||
| EXPOSE 18080 |  | ||||||
|  |  | ||||||
| CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karideo.WebLauncher"] |  | ||||||
|  |  | ||||||
| @@ -11,7 +11,7 @@ mvn package | |||||||
| // download all dependency in out/maven/dependency | // download all dependency in out/maven/dependency | ||||||
| mvn dependency:copy-dependencies | mvn dependency:copy-dependencies | ||||||
|  |  | ||||||
| java -cp out/maven/kar-karideo-0.1.0.jar  org.kar.karideo.WebLauncher | java -cp out/maven/kar-karideo-0.1.0.jar  org.atriasoft.karideo.WebLauncher | ||||||
|  |  | ||||||
|  |  | ||||||
| // create a single package jar | // create a single package jar | ||||||
| @@ -19,7 +19,7 @@ mvn clean compile assembly:single | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| java -cp out/maven/karideo-0.1.0-jar-with-dependencies.jar org.kar.karideo.WebLauncher | java -cp out/maven/karideo-0.1.0-jar-with-dependencies.jar org.atriasoft.karideo.WebLauncher | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										198
									
								
								back/pom.xml
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								back/pom.xml
									
									
									
									
									
								
							| @@ -1,31 +1,47 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | <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> | 	<modelVersion>4.0.0</modelVersion> | ||||||
| 	<groupId>org.kar</groupId> | 	<groupId>org.atriasoft</groupId> | ||||||
| 	<artifactId>karideo</artifactId> | 	<artifactId>karideo</artifactId> | ||||||
| 	<version>0.2.0</version> | 	<version>0.3.0</version> | ||||||
| 	<properties> | 	<properties> | ||||||
| 		<maven.compiler.version>3.1</maven.compiler.version> | 		<maven.compiler.version>3.13.0</maven.compiler.version> | ||||||
| 		<maven.compiler.source>21</maven.compiler.source> | 		<maven.compiler.source>23</maven.compiler.source> | ||||||
| 		<maven.compiler.target>21</maven.compiler.target> | 		<maven.compiler.target>23</maven.compiler.target> | ||||||
| 		<maven.dependency.version>3.1.1</maven.dependency.version> | 		<maven.dependency.version>3.1.1</maven.dependency.version> | ||||||
| 	</properties> | 	</properties> | ||||||
| 	<repositories> |  | ||||||
| 		<repository> |  | ||||||
| 			<id>gitea</id> |  | ||||||
| 			<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> |  | ||||||
| 		</repository> |  | ||||||
| 	</repositories> |  | ||||||
| 	<dependencies> | 	<dependencies> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>kangaroo-and-rabbit</groupId> | 			<groupId>org.atria-soft</groupId> | ||||||
| 			<artifactId>archidata</artifactId> | 			<artifactId>archidata</artifactId> | ||||||
| 			<version>0.6.1</version> | 			<version>0.37.2</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- Loopback of logger JDK logging API to SLF4J --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.slf4j</groupId> | 			<groupId>org.slf4j</groupId> | ||||||
| 			<artifactId>slf4j-simple</artifactId> | 			<artifactId>jul-to-slf4j</artifactId> | ||||||
| 			<version>2.0.9</version> | 			<version>2.1.0-alpha1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- generic logger of SLF4J to console (in color) --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>ch.qos.logback</groupId> | ||||||
|  | 			<artifactId>logback-classic</artifactId> | ||||||
|  | 			<version>1.5.19</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>xerces</groupId> | ||||||
|  | 			<artifactId>xercesImpl</artifactId> | ||||||
|  | 			<version>2.12.2</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.codehaus.janino</groupId> | ||||||
|  | 			<artifactId>janino</artifactId> | ||||||
|  | 			<version>3.1.12</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||||
|  | 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||||
|  | 			<version>2.20.0</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- | 		<!-- | ||||||
| 		************************************************************  | 		************************************************************  | ||||||
| @@ -35,15 +51,25 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-api</artifactId> | 			<artifactId>junit-jupiter-api</artifactId> | ||||||
| 			<version>5.10.1</version> | 			<version>6.0.0</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 	    <dependency> | 		<dependency> | ||||||
| 	        <groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 	        <artifactId>junit-jupiter-engine</artifactId> | 			<artifactId>junit-jupiter-engine</artifactId> | ||||||
| 			<version>5.10.1</version> | 			<version>6.0.0</version> | ||||||
| 	        <scope>test</scope> | 			<scope>test</scope> | ||||||
| 	    </dependency> | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 			<artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 			<version>2.29.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 			<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
|  | 			<version>3.6.0</version> | ||||||
|  | 		</dependency> | ||||||
| 	</dependencies> | 	</dependencies> | ||||||
| 	<build> | 	<build> | ||||||
| 		<sourceDirectory>src</sourceDirectory> | 		<sourceDirectory>src</sourceDirectory> | ||||||
| @@ -72,16 +98,45 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.codehaus.mojo</groupId> | 				<groupId>org.codehaus.mojo</groupId> | ||||||
| 				<artifactId>exec-maven-plugin</artifactId> | 				<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.karideo.WebLauncher</mainClass> | ||||||
|  | 						</configuration> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>dev-mode</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>java</goal> | ||||||
|  | 						</goals> | ||||||
|  | 						<configuration> | ||||||
|  | 							<mainClass>org.atriasoft.karideo.WebLauncherLocal</mainClass> | ||||||
|  | 						</configuration> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>generate-api</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>java</goal> | ||||||
|  | 						</goals> | ||||||
|  | 						<configuration> | ||||||
|  | 							<mainClass>org.atriasoft.karideo.GenerateApi</mainClass> | ||||||
|  | 						</configuration> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<mainClass>org.kar.karideo.WebLauncher</mainClass> | 					<mainClass/> | ||||||
| 				</configuration> | 				</configuration> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			<!-- Create the source bundle --> | 			<!-- Create the source bundle --> | ||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-source-plugin</artifactId> | 				<artifactId>maven-source-plugin</artifactId> | ||||||
| 				<version>3.2.1</version> | 				<version>4.0.0-beta-1</version> | ||||||
| 				<executions> | 				<executions> | ||||||
| 					<execution> | 					<execution> | ||||||
| 						<id>attach-sources</id> | 						<id>attach-sources</id> | ||||||
| @@ -95,10 +150,12 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-surefire-plugin</artifactId> | 				<artifactId>maven-surefire-plugin</artifactId> | ||||||
| 				<version>3.0.0-M5</version> | 				<version>3.2.5</version> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			<plugin> | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-assembly-plugin</artifactId> | 				<artifactId>maven-assembly-plugin</artifactId> | ||||||
|  | 				<version>3.7.1</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<archive> | 					<archive> | ||||||
| 						<manifest> | 						<manifest> | ||||||
| @@ -110,94 +167,21 @@ | |||||||
| 					</descriptorRefs> | 					</descriptorRefs> | ||||||
| 				</configuration> | 				</configuration> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			<!-- Create coverage --> |  | ||||||
| 			<!-- |  | ||||||
| 			<plugin> |  | ||||||
| 				<groupId>org.jacoco</groupId> |  | ||||||
| 				<artifactId>jacoco-maven-plugin</artifactId> |  | ||||||
| 				<version>0.8.10</version> |  | ||||||
| 				<executions> |  | ||||||
| 					<execution> |  | ||||||
| 						<id>prepare-agent</id> |  | ||||||
| 						<goals> |  | ||||||
| 							<goal>prepare-agent</goal> |  | ||||||
| 						</goals> |  | ||||||
| 					</execution> |  | ||||||
| 					<execution> |  | ||||||
| 						<id>report</id> |  | ||||||
| 						<phase>test</phase> |  | ||||||
| 						<goals> |  | ||||||
| 							<goal>report</goal> |  | ||||||
| 						</goals> |  | ||||||
| 					</execution> |  | ||||||
| 					<execution> |  | ||||||
| 						<id>jacoco-check</id> |  | ||||||
| 						<goals> |  | ||||||
| 							<goal>check</goal> |  | ||||||
| 						</goals> |  | ||||||
| 						<configuration> |  | ||||||
| 							<rules> |  | ||||||
| 								<rule> |  | ||||||
| 									<element>PACKAGE</element> |  | ||||||
| 									<limits> |  | ||||||
| 										<limit> |  | ||||||
| 											<counter>LINE</counter> |  | ||||||
| 											<value>COVEREDRATIO</value> |  | ||||||
| 											<minimum>0.50</minimum> |  | ||||||
| 										</limit> |  | ||||||
| 									</limits> |  | ||||||
| 								</rule> |  | ||||||
| 							</rules> |  | ||||||
| 						</configuration> |  | ||||||
| 					</execution> |  | ||||||
| 				</executions> |  | ||||||
| 			</plugin> |  | ||||||
| 			--> |  | ||||||
| 			<!-- Java-doc generation for stand-alone site --> | 			<!-- Java-doc generation for stand-alone site --> | ||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-javadoc-plugin</artifactId> | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
| 				<version>3.2.0</version> | 				<version>3.3.0</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<show>private</show> | 					<show>private</show> | ||||||
| 					<nohelp>true</nohelp> | 					<nohelp>true</nohelp> | ||||||
| 				</configuration> | 				</configuration> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			<plugin> |  | ||||||
| 				<groupId>org.codehaus.mojo</groupId> |  | ||||||
| 				<artifactId>exec-maven-plugin</artifactId> |  | ||||||
| 				<version>3.1.0</version> |  | ||||||
| 				<executions> |  | ||||||
| 					<execution> |  | ||||||
| 						<id>exec-application</id> |  | ||||||
| 						<phase>package</phase> |  | ||||||
| 						<goals> |  | ||||||
| 							<goal>java</goal> |  | ||||||
| 						</goals> |  | ||||||
| 					</execution> |  | ||||||
| 				</executions> |  | ||||||
| 				<configuration> |  | ||||||
| 					<mainClass>org.kar.karideo.WebLauncher</mainClass> |  | ||||||
| 				</configuration> |  | ||||||
| 			</plugin> |  | ||||||
| 			<!-- Check the style of the code --> | 			<!-- Check the style of the code --> | ||||||
| 			<!-- |  | ||||||
| 			<plugin> |  | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> |  | ||||||
| 				<artifactId>maven-checkstyle-plugin</artifactId> |  | ||||||
| 				<version>3.1.0</version> |  | ||||||
| 				<configuration> |  | ||||||
| 					<configLocation>CheckStyle.xml</configLocation> |  | ||||||
| 					<consoleOutput>true</consoleOutput> |  | ||||||
| 					<failOnViolation>true</failOnViolation> |  | ||||||
| 					<failsOnError>true</failsOnError> |  | ||||||
| 					<includeTestSourceDirectory>true</includeTestSourceDirectory> |  | ||||||
| 				</configuration> |  | ||||||
| 			</plugin> |  | ||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>net.revelc.code.formatter</groupId> | 				<groupId>net.revelc.code.formatter</groupId> | ||||||
| 				<artifactId>formatter-maven-plugin</artifactId> | 				<artifactId>formatter-maven-plugin</artifactId> | ||||||
| 				<version>2.12.2</version> | 				<version>2.24.1</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<encoding>UTF-8</encoding> | 					<encoding>UTF-8</encoding> | ||||||
| 					<lineEnding>LF</lineEnding> | 					<lineEnding>LF</lineEnding> | ||||||
| @@ -221,7 +205,15 @@ | |||||||
| 					</execution> | 					</execution> | ||||||
| 				</executions> | 				</executions> | ||||||
| 			</plugin> | 			</plugin> | ||||||
| 			--> | 			<plugin> | ||||||
|  | 				<groupId>com.github.spotbugs</groupId> | ||||||
|  | 				<artifactId>spotbugs-maven-plugin</artifactId> | ||||||
|  | 				<version>4.8.5.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<includeFilterFile>spotbugs-security-include.xml</includeFilterFile> | ||||||
|  | 					<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
| 		</plugins> | 		</plugins> | ||||||
| 	</build> | 	</build> | ||||||
| 	<!-- Generate Java-docs As Part Of Project Reports --> | 	<!-- Generate Java-docs As Part Of Project Reports --> | ||||||
| @@ -230,7 +222,7 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-javadoc-plugin</artifactId> | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
| 				<version>3.2.0</version> | 				<version>3.3.0</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<show>public</show> | 					<show>public</show> | ||||||
| 				</configuration> | 				</configuration> | ||||||
|   | |||||||
							
								
								
									
										245
									
								
								back/pom.xml.versionsBackup
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								back/pom.xml.versionsBackup
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  | 	<modelVersion>4.0.0</modelVersion> | ||||||
|  | 	<groupId>org.kar</groupId> | ||||||
|  | 	<artifactId>karideo</artifactId> | ||||||
|  | 	<version>0.3.0</version> | ||||||
|  | 	<properties> | ||||||
|  | 		<maven.compiler.version>3.1</maven.compiler.version> | ||||||
|  | 		<maven.compiler.source>21</maven.compiler.source> | ||||||
|  | 		<maven.compiler.target>21</maven.compiler.target> | ||||||
|  | 		<maven.dependency.version>3.1.1</maven.dependency.version> | ||||||
|  | 	</properties> | ||||||
|  | 	<repositories> | ||||||
|  | 		<repository> | ||||||
|  | 			<id>gitea</id> | ||||||
|  | 			<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> | ||||||
|  | 		</repository> | ||||||
|  | 	</repositories> | ||||||
|  | 	<dependencies> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>kangaroo-and-rabbit</groupId> | ||||||
|  | 			<artifactId>archidata</artifactId> | ||||||
|  | 			<version>0.11.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.slf4j</groupId> | ||||||
|  | 			<artifactId>slf4j-simple</artifactId> | ||||||
|  | 			<version>2.0.9</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||||
|  | 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||||
|  | 			<version>2.16.1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- | ||||||
|  | 		************************************************************  | ||||||
|  | 		** TEST dependency                                        ** | ||||||
|  | 		************************************************************ | ||||||
|  | 		--> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.junit.jupiter</groupId> | ||||||
|  | 			<artifactId>junit-jupiter-api</artifactId> | ||||||
|  | 			<version>5.10.1</version> | ||||||
|  | 			<scope>test</scope> | ||||||
|  | 		</dependency> | ||||||
|  | 	    <dependency> | ||||||
|  | 	        <groupId>org.junit.jupiter</groupId> | ||||||
|  | 	        <artifactId>junit-jupiter-engine</artifactId> | ||||||
|  | 			<version>5.10.1</version> | ||||||
|  | 	        <scope>test</scope> | ||||||
|  | 	    </dependency> | ||||||
|  | 	</dependencies> | ||||||
|  | 	<build> | ||||||
|  | 		<sourceDirectory>src</sourceDirectory> | ||||||
|  | 		<testSourceDirectory>test/src</testSourceDirectory> | ||||||
|  | 		<directory>${project.basedir}/out/maven/</directory> | ||||||
|  | 		<resources> | ||||||
|  | 			<resource> | ||||||
|  | 				<directory>src/resources</directory> | ||||||
|  | 			</resource> | ||||||
|  | 		</resources> | ||||||
|  | 		<testResources> | ||||||
|  | 			<testResource> | ||||||
|  | 				<directory>${basedir}/test/resources</directory> | ||||||
|  | 			</testResource> | ||||||
|  | 		</testResources> | ||||||
|  | 		<plugins> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-compiler-plugin</artifactId> | ||||||
|  | 				<version>${maven.compiler.version}</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<source>${maven.compiler.source}</source> | ||||||
|  | 					<target>${maven.compiler.target}</target> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.codehaus.mojo</groupId> | ||||||
|  | 				<artifactId>exec-maven-plugin</artifactId> | ||||||
|  | 				<version>1.4.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<mainClass>org.kar.karideo.WebLauncher</mainClass> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Create the source bundle --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-source-plugin</artifactId> | ||||||
|  | 				<version>3.2.1</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>attach-sources</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>jar</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- junit results --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-surefire-plugin</artifactId> | ||||||
|  | 				<version>3.0.0-M5</version> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<artifactId>maven-assembly-plugin</artifactId> | ||||||
|  | 				<configuration> | ||||||
|  | 					<archive> | ||||||
|  | 						<manifest> | ||||||
|  | 							<mainClass>fully.qualified.MainClass</mainClass> | ||||||
|  | 						</manifest> | ||||||
|  | 					</archive> | ||||||
|  | 					<descriptorRefs> | ||||||
|  | 						<descriptorRef>jar-with-dependencies</descriptorRef> | ||||||
|  | 					</descriptorRefs> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Create coverage --> | ||||||
|  | 			<!-- | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.jacoco</groupId> | ||||||
|  | 				<artifactId>jacoco-maven-plugin</artifactId> | ||||||
|  | 				<version>0.8.10</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>prepare-agent</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>prepare-agent</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>report</id> | ||||||
|  | 						<phase>test</phase> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>report</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>jacoco-check</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>check</goal> | ||||||
|  | 						</goals> | ||||||
|  | 						<configuration> | ||||||
|  | 							<rules> | ||||||
|  | 								<rule> | ||||||
|  | 									<element>PACKAGE</element> | ||||||
|  | 									<limits> | ||||||
|  | 										<limit> | ||||||
|  | 											<counter>LINE</counter> | ||||||
|  | 											<value>COVEREDRATIO</value> | ||||||
|  | 											<minimum>0.50</minimum> | ||||||
|  | 										</limit> | ||||||
|  | 									</limits> | ||||||
|  | 								</rule> | ||||||
|  | 							</rules> | ||||||
|  | 						</configuration> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			--> | ||||||
|  | 			<!-- Java-doc generation for stand-alone site --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
|  | 				<version>3.2.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<show>private</show> | ||||||
|  | 					<nohelp>true</nohelp> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.codehaus.mojo</groupId> | ||||||
|  | 				<artifactId>exec-maven-plugin</artifactId> | ||||||
|  | 				<version>3.1.0</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>exec-application</id> | ||||||
|  | 						<phase>package</phase> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>java</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 				<configuration> | ||||||
|  | 					<mainClass>org.kar.karideo.WebLauncher</mainClass> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<!-- Check the style of the code --> | ||||||
|  | 			<!-- | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
|  | 				<version>3.1.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<configLocation>CheckStyle.xml</configLocation> | ||||||
|  | 					<consoleOutput>true</consoleOutput> | ||||||
|  | 					<failOnViolation>true</failOnViolation> | ||||||
|  | 					<failsOnError>true</failsOnError> | ||||||
|  | 					<includeTestSourceDirectory>true</includeTestSourceDirectory> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 				<artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 				<version>2.12.2</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<encoding>UTF-8</encoding> | ||||||
|  | 					<lineEnding>LF</lineEnding> | ||||||
|  | 					<configFile>Formatter.xml</configFile> | ||||||
|  | 					<directories> | ||||||
|  | 						<directory>src/</directory> | ||||||
|  | 						<directory>test/src</directory> | ||||||
|  | 					</directories> | ||||||
|  | 					<includes> | ||||||
|  | 						<include>**/*.java</include> | ||||||
|  | 					</includes> | ||||||
|  | 					<excludes> | ||||||
|  | 						<exclude>module-info.java</exclude> | ||||||
|  | 					</excludes> | ||||||
|  | 				</configuration> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>validate</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
|  | 			--> | ||||||
|  | 		</plugins> | ||||||
|  | 	</build> | ||||||
|  | 	<!-- Generate Java-docs As Part Of Project Reports --> | ||||||
|  | 	<reporting> | ||||||
|  | 		<plugins> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 				<artifactId>maven-javadoc-plugin</artifactId> | ||||||
|  | 				<version>3.2.0</version> | ||||||
|  | 				<configuration> | ||||||
|  | 					<show>public</show> | ||||||
|  | 				</configuration> | ||||||
|  | 			</plugin> | ||||||
|  | 		</plugins> | ||||||
|  | 	</reporting> | ||||||
|  | </project> | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| org.kar.karideo.dataTmpFolder=/application/data/tmp | org.atriasoft.karideo.dataTmpFolder=/application/data/tmp | ||||||
| org.kar.karideo.dataTmpFolder=/application/data/media | org.atriasoft.karideo.dataTmpFolder=/application/data/media | ||||||
| org.kar.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/ | org.atriasoft.karideo.rest.oauth=http://192.168.1.156:21080/oauth/api/ | ||||||
| org.kar.karideo.db.host=1992.156.1.156 | org.atriasoft.karideo.db.host=1992.156.1.156 | ||||||
| org.kar.karideo.db.port=20306 | org.atriasoft.karideo.db.port=20306 | ||||||
| org.kar.karideo.db.login=root | org.atriasoft.karideo.db.login=root | ||||||
| org.kar.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh | org.atriasoft.karideo.db.port=klkhj456gkgtkhjgvkujfhjgkjhgsdfhb3467465fgdhdesfgh | ||||||
| org.kar.karideo.db.name=karideo | org.atriasoft.karideo.db.name=karideo | ||||||
| org.kar.karideo.address=http://0.0.0.0:18080/karideo/api/ | org.atriasoft.karideo.address=http://0.0.0.0:18080/karideo/api/ | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								back/src/org/atriasoft/karideo/GenerateApi.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								back/src/org/atriasoft/karideo/GenerateApi.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | package org.atriasoft.karideo; | ||||||
|  |  | ||||||
|  | import org.atriasoft.karideo.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,50 +1,53 @@ | |||||||
| package org.kar.karideo; | package org.atriasoft.karideo; | ||||||
| 
 | 
 | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
|  | import java.util.TimeZone; | ||||||
|  | import java.util.logging.LogManager; | ||||||
| 
 | 
 | ||||||
|  | import org.atriasoft.archidata.UpdateJwtPublicKey; | ||||||
|  | import org.atriasoft.archidata.api.DataResource; | ||||||
|  | import org.atriasoft.archidata.catcher.GenericCatcher; | ||||||
|  | import org.atriasoft.archidata.cron.CronScheduler; | ||||||
|  | import org.atriasoft.archidata.db.DbConfig; | ||||||
|  | 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.karideo.api.Front; | ||||||
|  | import org.atriasoft.karideo.api.HealthCheck; | ||||||
|  | import org.atriasoft.karideo.api.MediaResource; | ||||||
|  | import org.atriasoft.karideo.api.SeasonResource; | ||||||
|  | import org.atriasoft.karideo.api.SeriesResource; | ||||||
|  | import org.atriasoft.karideo.api.TypeResource; | ||||||
|  | import org.atriasoft.karideo.api.UserMediaAdvancementResource; | ||||||
|  | import org.atriasoft.karideo.api.UserResource; | ||||||
|  | import org.atriasoft.karideo.filter.KarideoAuthenticationFilter; | ||||||
|  | import org.atriasoft.karideo.job.BackupJob; | ||||||
|  | import org.atriasoft.karideo.migration.Initialization; | ||||||
| import org.glassfish.grizzly.http.server.HttpServer; | import org.glassfish.grizzly.http.server.HttpServer; | ||||||
| import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | ||||||
| import org.glassfish.jersey.jackson.JacksonFeature; | import org.glassfish.jersey.jackson.JacksonFeature; | ||||||
| import org.glassfish.jersey.media.multipart.MultiPartFeature; | import org.glassfish.jersey.media.multipart.MultiPartFeature; | ||||||
| import org.glassfish.jersey.server.ResourceConfig; | import org.glassfish.jersey.server.ResourceConfig; | ||||||
| import org.kar.archidata.GlobalConfiguration; | import org.glassfish.jersey.server.validation.ValidationFeature; | ||||||
| import org.kar.archidata.UpdateJwtPublicKey; |  | ||||||
| import org.kar.archidata.api.DataResource; |  | ||||||
| import org.kar.archidata.catcher.ExceptionCatcher; |  | ||||||
| import org.kar.archidata.catcher.FailExceptionCatcher; |  | ||||||
| import org.kar.archidata.catcher.InputExceptionCatcher; |  | ||||||
| import org.kar.archidata.catcher.SystemExceptionCatcher; |  | ||||||
| import org.kar.archidata.db.DBConfig; |  | ||||||
| import org.kar.archidata.filter.CORSFilter; |  | ||||||
| import org.kar.archidata.filter.OptionFilter; |  | ||||||
| import org.kar.archidata.migration.MigrationEngine; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.kar.karideo.api.Front; |  | ||||||
| import org.kar.karideo.api.HealthCheck; |  | ||||||
| import org.kar.karideo.api.SeasonResource; |  | ||||||
| import org.kar.karideo.api.SeriesResource; |  | ||||||
| import org.kar.karideo.api.TypeResource; |  | ||||||
| import org.kar.karideo.api.UserMediaAdvancementResource; |  | ||||||
| import org.kar.karideo.api.UserResource; |  | ||||||
| import org.kar.karideo.api.VideoResource; |  | ||||||
| import org.kar.karideo.filter.KarideoAuthenticationFilter; |  | ||||||
| import org.kar.karideo.migration.Initialization; |  | ||||||
| import org.kar.karideo.migration.Migration20230810; |  | ||||||
| import org.kar.karideo.migration.Migration20231015; |  | ||||||
| import org.kar.karideo.migration.Migration20231126; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | import org.slf4j.bridge.SLF4JBridgeHandler; | ||||||
| 
 | 
 | ||||||
| import jakarta.ws.rs.core.UriBuilder; | import jakarta.ws.rs.core.UriBuilder; | ||||||
| 
 | 
 | ||||||
| public class WebLauncher { | public class WebLauncher { | ||||||
| 	final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class); | 	final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class); | ||||||
| 	public static DBConfig dbConfig; |  | ||||||
| 	protected UpdateJwtPublicKey keyUpdater = null; | 	protected UpdateJwtPublicKey keyUpdater = null; | ||||||
| 	protected HttpServer server = null; | 	protected HttpServer server = null; | ||||||
|  | 	protected CronScheduler scheduler = null; | ||||||
| 
 | 
 | ||||||
| 	public WebLauncher() { | 	public WebLauncher() { | ||||||
|  | 		TimeZone.setDefault(TimeZone.getTimeZone("UTC")); | ||||||
| 		ConfigBaseVariable.bdDatabase = "karideo"; | 		ConfigBaseVariable.bdDatabase = "karideo"; | ||||||
|  | 		this.scheduler = new CronScheduler(); | ||||||
|  | 		this.scheduler.setGracePeriodMinutes(1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static URI getBaseURI() { | 	private static URI getBaseURI() { | ||||||
| @@ -57,16 +60,17 @@ public class WebLauncher { | |||||||
| 		WebLauncher.LOGGER.info("Add initialization"); | 		WebLauncher.LOGGER.info("Add initialization"); | ||||||
| 		migrationEngine.setInit(new Initialization()); | 		migrationEngine.setInit(new Initialization()); | ||||||
| 		WebLauncher.LOGGER.info("Add migration since last version"); | 		WebLauncher.LOGGER.info("Add migration since last version"); | ||||||
| 		migrationEngine.add(new Migration20230810()); | 		// migrationEngine.add(new Migration20250928()); | ||||||
| 		migrationEngine.add(new Migration20231015()); |  | ||||||
| 		migrationEngine.add(new Migration20231126()); |  | ||||||
| 		//migrationEngine.add(new Migration20231126()); |  | ||||||
| 		WebLauncher.LOGGER.info("Migrate the DB [START]"); | 		WebLauncher.LOGGER.info("Migrate the DB [START]"); | ||||||
| 		migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); | 		migrationEngine.migrateWaitAdmin(new DbConfig()); | ||||||
| 		WebLauncher.LOGGER.info("Migrate the DB [STOP]"); | 		WebLauncher.LOGGER.info("Migrate the DB [STOP]"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static void main(final String[] args) throws Exception { | 	public static void main(final String[] args) throws Exception { | ||||||
|  | 		// Loop-back of logger JDK logging API to SLF4J | ||||||
|  | 		LogManager.getLogManager().reset(); | ||||||
|  | 		SLF4JBridgeHandler.install(); | ||||||
|  | 
 | ||||||
| 		WebLauncher.LOGGER.info("[START] application wake UP"); | 		WebLauncher.LOGGER.info("[START] application wake UP"); | ||||||
| 		final WebLauncher launcher = new WebLauncher(); | 		final WebLauncher launcher = new WebLauncher(); | ||||||
| 		launcher.migrateDB(); | 		launcher.migrateDB(); | ||||||
| @@ -78,7 +82,7 @@ public class WebLauncher { | |||||||
| 		WebLauncher.LOGGER.info("STOP the REST server"); | 		WebLauncher.LOGGER.info("STOP the REST server"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void process() throws InterruptedException { | 	public void process() throws Exception { | ||||||
| 
 | 
 | ||||||
| 		// =================================================================== | 		// =================================================================== | ||||||
| 		// Configure resources | 		// Configure resources | ||||||
| @@ -94,29 +98,32 @@ public class WebLauncher { | |||||||
| 		// global authentication system | 		// global authentication system | ||||||
| 		rc.register(KarideoAuthenticationFilter.class); | 		rc.register(KarideoAuthenticationFilter.class); | ||||||
| 		// register exception catcher | 		// register exception catcher | ||||||
| 		rc.register(InputExceptionCatcher.class); | 		GenericCatcher.addAll(rc); | ||||||
| 		rc.register(SystemExceptionCatcher.class); |  | ||||||
| 		rc.register(FailExceptionCatcher.class); |  | ||||||
| 		rc.register(ExceptionCatcher.class); |  | ||||||
| 		// add default resource: | 		// add default resource: | ||||||
| 		rc.register(UserResource.class); | 		rc.register(UserResource.class); | ||||||
| 		rc.register(SeriesResource.class); | 		rc.register(SeriesResource.class); | ||||||
| 		rc.register(DataResource.class); | 		rc.register(DataResource.class); | ||||||
| 		rc.register(SeasonResource.class); | 		rc.register(SeasonResource.class); | ||||||
| 		rc.register(TypeResource.class); | 		rc.register(TypeResource.class); | ||||||
| 		rc.register(VideoResource.class); | 		rc.register(MediaResource.class); | ||||||
| 		rc.register(UserMediaAdvancementResource.class); | 		rc.register(UserMediaAdvancementResource.class); | ||||||
| 
 | 
 | ||||||
| 		rc.register(HealthCheck.class); | 		rc.register(HealthCheck.class); | ||||||
| 		rc.register(Front.class); | 		rc.register(Front.class); | ||||||
| 
 | 		ContextGenericTools.addJsr310(rc); | ||||||
| 		// add jackson to be discover when we are ins stand-alone server | 		// add jackson to be discover when we are ins stand-alone server | ||||||
| 		rc.register(JacksonFeature.class); | 		rc.register(JacksonFeature.class); | ||||||
|  | 		// enable jersey specific validations (@Valid) | ||||||
|  | 		rc.register(ValidationFeature.class); | ||||||
| 		// enable this to show low level request | 		// enable this to show low level request | ||||||
| 		//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); | 		// rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); | ||||||
| 
 | 
 | ||||||
| 		this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); | 		this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); | ||||||
| 		final HttpServer serverLink = this.server; | 		final HttpServer serverLink = this.server; | ||||||
|  | 		// for (final NetworkListener listener : serverLink.getListeners()) { | ||||||
|  | 		// listener.getKeepAlive().setIdleTimeoutInSeconds(30); // Set idle timeout | ||||||
|  | 		// listener.getKeepAlive().setMaxRequestsCount(80); // Set request timeout | ||||||
|  | 		// } | ||||||
| 		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { | 		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { | ||||||
| 			@Override | 			@Override | ||||||
| 			public void run() { | 			public void run() { | ||||||
| @@ -131,6 +138,14 @@ public class WebLauncher { | |||||||
| 		this.keyUpdater = new UpdateJwtPublicKey(); | 		this.keyUpdater = new UpdateJwtPublicKey(); | ||||||
| 		this.keyUpdater.start(); | 		this.keyUpdater.start(); | ||||||
| 
 | 
 | ||||||
|  | 		// =================================================================== | ||||||
|  | 		// start generic scheduler ... | ||||||
|  | 		// =================================================================== | ||||||
|  | 		this.scheduler.addTask("backup", "0 0 * * *", new BackupJob()); | ||||||
|  | 		this.scheduler.start(); | ||||||
|  | 		// execute a backup before start... | ||||||
|  | 		new BackupJob().run(); | ||||||
|  | 
 | ||||||
| 		// =================================================================== | 		// =================================================================== | ||||||
| 		// run JERSEY | 		// run JERSEY | ||||||
| 		// =================================================================== | 		// =================================================================== | ||||||
| @@ -148,6 +163,10 @@ public class WebLauncher { | |||||||
| 			this.server.shutdownNow(); | 			this.server.shutdownNow(); | ||||||
| 			this.server = null; | 			this.server = null; | ||||||
| 		} | 		} | ||||||
|  | 		if (this.scheduler != null) { | ||||||
|  | 			this.scheduler.stop(); | ||||||
|  | 			this.scheduler = null; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void stopOther() { | 	public void stopOther() { | ||||||
| @@ -1,16 +1,26 @@ | |||||||
| 
 | 
 | ||||||
| package org.kar.karideo; | package org.atriasoft.karideo; | ||||||
| 
 | 
 | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import java.util.logging.LogManager; | ||||||
|  | 
 | ||||||
|  | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.atriasoft.karideo.migration.Initialization; | ||||||
|  | import org.atriasoft.karideo.util.ConfigVariable; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | import org.slf4j.bridge.SLF4JBridgeHandler; | ||||||
| 
 | 
 | ||||||
| public class WebLauncherLocal extends WebLauncher { | public class WebLauncherLocal extends WebLauncher { | ||||||
| 	private final static Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(WebLauncherLocal.class); | ||||||
| 
 | 
 | ||||||
| 	private WebLauncherLocal() {} | 	private WebLauncherLocal() {} | ||||||
| 
 | 
 | ||||||
| 	public static void main(final String[] args) throws InterruptedException { | 	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(); | 		final WebLauncherLocal launcher = new WebLauncherLocal(); | ||||||
| 		launcher.process(); | 		launcher.process(); | ||||||
| 		LOGGER.info("end-configure the server & wait finish process:"); | 		LOGGER.info("end-configure the server & wait finish process:"); | ||||||
| @@ -19,11 +29,15 @@ public class WebLauncherLocal extends WebLauncher { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void process() throws InterruptedException { | 	public void process() throws Exception { | ||||||
| 		if (true) { | 		if (true) { | ||||||
| 			// for local test: | 			// for local test: | ||||||
| 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:18080/karideo/api/"; | 			ConfigBaseVariable.apiAdress = "http://0.0.0.0:18080/karideo/api/"; | ||||||
| 			ConfigBaseVariable.dbPort = "3906"; | 			ConfigBaseVariable.testMode = "true"; | ||||||
|  | 			ConfigBaseVariable.dbType = "mongo"; | ||||||
|  | 		} | ||||||
|  | 		if (ConfigVariable.isInitWithBackup()) { | ||||||
|  | 			Initialization.initializeWithBackup(); | ||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
| 			super.migrateDB(); | 			super.migrateDB(); | ||||||
							
								
								
									
										502
									
								
								back/src/org/atriasoft/karideo/api/DataResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										502
									
								
								back/src/org/atriasoft/karideo/api/DataResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,502 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.awt.Graphics2D; | ||||||
|  | import java.awt.image.BufferedImage; | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.FileInputStream; | ||||||
|  | import java.io.FileNotFoundException; | ||||||
|  | import java.io.FileOutputStream; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.io.RandomAccessFile; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Paths; | ||||||
|  | import java.nio.file.StandardCopyOption; | ||||||
|  | import java.security.MessageDigest; | ||||||
|  | import java.security.NoSuchAlgorithmException; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import javax.imageio.ImageIO; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional; | ||||||
|  | import org.atriasoft.archidata.annotation.security.PermitTokenInURI; | ||||||
|  | import org.atriasoft.archidata.api.MediaStreamer; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.Condition; | ||||||
|  | import org.atriasoft.archidata.exception.FailException; | ||||||
|  | import org.atriasoft.archidata.filter.GenericContext; | ||||||
|  | import org.atriasoft.archidata.model.Data; | ||||||
|  | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
|  | 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 io.swagger.v3.oas.annotations.Operation; | ||||||
|  | import jakarta.annotation.security.RolesAllowed; | ||||||
|  | import jakarta.ws.rs.Consumes; | ||||||
|  | import jakarta.ws.rs.GET; | ||||||
|  | import jakarta.ws.rs.HeaderParam; | ||||||
|  | import jakarta.ws.rs.InternalServerErrorException; | ||||||
|  | import jakarta.ws.rs.POST; | ||||||
|  | import jakarta.ws.rs.Path; | ||||||
|  | import jakarta.ws.rs.PathParam; | ||||||
|  | import jakarta.ws.rs.Produces; | ||||||
|  | import jakarta.ws.rs.QueryParam; | ||||||
|  | import jakarta.ws.rs.core.CacheControl; | ||||||
|  | import jakarta.ws.rs.core.Context; | ||||||
|  | import jakarta.ws.rs.core.HttpHeaders; | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.Response; | ||||||
|  | import jakarta.ws.rs.core.SecurityContext; | ||||||
|  | import jakarta.ws.rs.core.StreamingOutput; | ||||||
|  |  | ||||||
|  | // https://stackoverflow.com/questions/35367113/jersey-webservice-scalable-approach-to-download-file-and-reply-to-client | ||||||
|  | // https://gist.github.com/aitoroses/4f7a2b197b732a6a691d | ||||||
|  |  | ||||||
|  | @Path("/data") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class DataResource { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(DataResource.class); | ||||||
|  | 	private final static int CHUNK_SIZE = 1024 * 1024; // 1MB chunks | ||||||
|  | 	private final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks | ||||||
|  | 	/** Upload some datas */ | ||||||
|  | 	private static long tmpFolderId = 1; | ||||||
|  |  | ||||||
|  | 	private static void createFolder(final String path) throws IOException { | ||||||
|  | 		if (!Files.exists(Paths.get(path))) { | ||||||
|  | 			Files.createDirectories(Paths.get(path)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static long getTmpDataId() { | ||||||
|  | 		return tmpFolderId++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String getTmpFileInData(final long tmpFolderId) { | ||||||
|  | 		final String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId; | ||||||
|  | 		try { | ||||||
|  | 			createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator); | ||||||
|  | 		} catch (final IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return filePath; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String getFileDataOld(final UUID uuid) { | ||||||
|  | 		final String stringUUID = uuid.toString(); | ||||||
|  | 		final String part1 = stringUUID.substring(0, 2); | ||||||
|  | 		final String part2 = stringUUID.substring(2, 4); | ||||||
|  | 		final String part3 = stringUUID.substring(4); | ||||||
|  | 		final String finalPath = part1 + File.separator + part2; | ||||||
|  | 		String filePath = ConfigBaseVariable.getMediaDataFolder() + "_uuid" + File.separator + finalPath + File.separator; | ||||||
|  | 		try { | ||||||
|  | 			createFolder(filePath); | ||||||
|  | 		} catch (final IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		filePath += part3; | ||||||
|  | 		return filePath; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String getFileData(final ObjectId oid) { | ||||||
|  | 		final String stringOid = oid.toHexString(); | ||||||
|  | 		String dir1 = stringOid.substring(0, 2); | ||||||
|  | 		String dir2 = stringOid.substring(2, 4); | ||||||
|  | 		String dir3 = stringOid.substring(4, 6); | ||||||
|  | 		try { | ||||||
|  | 			final MessageDigest digest = MessageDigest.getInstance("SHA-256"); | ||||||
|  | 			final byte[] hashBytes = digest.digest(oid.toByteArray()); | ||||||
|  | 			dir1 = String.format("%02x", hashBytes[0]); | ||||||
|  | 			dir2 = String.format("%02x", hashBytes[1]); | ||||||
|  | 			dir3 = String.format("%02x", hashBytes[2]); | ||||||
|  | 		} catch (final NoSuchAlgorithmException ex) { | ||||||
|  | 			LOGGER.error("Fail to generate the hash of the objectId ==> ise direct value ... {}", ex.getMessage()); | ||||||
|  | 		} | ||||||
|  | 		final String finalPath = dir1 + File.separator + dir2 + File.separator + dir3; | ||||||
|  | 		String filePath = ConfigBaseVariable.getMediaDataFolder() + "_oid" + File.separator + finalPath + File.separator; | ||||||
|  | 		try { | ||||||
|  | 			createFolder(filePath); | ||||||
|  | 		} catch (final IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		filePath += stringOid; | ||||||
|  | 		return filePath; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String getFileMetaData(final ObjectId oid) { | ||||||
|  | 		return getFileData(oid) + ".json"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Data getWithSha512(final String sha512) { | ||||||
|  | 		LOGGER.info("find sha512 = {}", sha512); | ||||||
|  | 		try { | ||||||
|  | 			return DataAccess.getWhere(Data.class, new Condition(new QueryCondition("sha512", "=", sha512))); | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Data getWithId(final long id) { | ||||||
|  | 		LOGGER.info("find id = {}", id); | ||||||
|  | 		try { | ||||||
|  | 			return DataAccess.get(Data.class, id); | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	protected String getMimeType(final String extension) throws IOException { | ||||||
|  | 		return switch (extension.toLowerCase()) { | ||||||
|  | 		case "jpg", "jpeg" -> "image/jpeg"; | ||||||
|  | 		case "png" -> "image/png"; | ||||||
|  | 		case "webp" -> "image/webp"; | ||||||
|  | 		case "mka" -> "audio/x-matroska"; | ||||||
|  | 		case "mkv" -> "video/x-matroska"; | ||||||
|  | 		case "webm" -> "video/webm"; | ||||||
|  | 		default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Data createNewData(final long tmpUID, final String originalFileName, final String sha512) throws IOException { | ||||||
|  | 		// determine mime type: | ||||||
|  | 		Data injectedData = new Data(); | ||||||
|  | 		String mimeType = ""; | ||||||
|  | 		final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); | ||||||
|  | 		mimeType = getMimeType(extension); | ||||||
|  | 		injectedData.mimeType = mimeType; | ||||||
|  | 		injectedData.sha512 = sha512; | ||||||
|  | 		final String tmpPath = getTmpFileInData(tmpUID); | ||||||
|  | 		injectedData.size = Files.size(Paths.get(tmpPath)); | ||||||
|  |  | ||||||
|  | 		try { | ||||||
|  | 			injectedData = DataAccess.insert(injectedData); | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		final String mediaPath = getFileData(injectedData.oid); | ||||||
|  | 		LOGGER.info("src = {}", tmpPath); | ||||||
|  | 		LOGGER.info("dst = {}", mediaPath); | ||||||
|  | 		Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE); | ||||||
|  | 		LOGGER.info("Move done"); | ||||||
|  | 		return injectedData; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void modeFileOldModelToNewModel(final UUID uuid, final ObjectId oid) throws IOException { | ||||||
|  | 		String mediaCurentPath = getFileDataOld(uuid); | ||||||
|  | 		String mediaDestPath = getFileData(oid); | ||||||
|  | 		LOGGER.info("src = {}", mediaCurentPath); | ||||||
|  | 		LOGGER.info("dst = {}", mediaDestPath); | ||||||
|  | 		if (Files.exists(Paths.get(mediaCurentPath))) { | ||||||
|  | 			LOGGER.info("move: {} ==> {}", mediaCurentPath, mediaDestPath); | ||||||
|  | 			Files.move(Paths.get(mediaCurentPath), Paths.get(mediaDestPath), StandardCopyOption.ATOMIC_MOVE); | ||||||
|  | 		} | ||||||
|  | 		// Move old meta-data... | ||||||
|  | 		mediaCurentPath = mediaCurentPath.substring(mediaCurentPath.length() - 4) + "meta.json"; | ||||||
|  | 		mediaDestPath = mediaCurentPath.substring(mediaDestPath.length() - 4) + "meta.json"; | ||||||
|  | 		if (Files.exists(Paths.get(mediaCurentPath))) { | ||||||
|  | 			LOGGER.info("moveM: {} ==> {}", mediaCurentPath, mediaDestPath); | ||||||
|  | 			Files.move(Paths.get(mediaCurentPath), Paths.get(mediaDestPath), StandardCopyOption.ATOMIC_MOVE); | ||||||
|  | 		} | ||||||
|  | 		LOGGER.info("Move done"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String saveTemporaryFile(final InputStream uploadedInputStream, final long idData) throws FailException { | ||||||
|  | 		return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void removeTemporaryFile(final long idData) { | ||||||
|  | 		final String filepath = DataResource.getTmpFileInData(idData); | ||||||
|  | 		if (Files.exists(Paths.get(filepath))) { | ||||||
|  | 			try { | ||||||
|  | 				Files.delete(Paths.get(filepath)); | ||||||
|  | 			} catch (final IOException e) { | ||||||
|  | 				LOGGER.info("can not delete temporary file : {}", Paths.get(filepath)); | ||||||
|  | 				e.printStackTrace(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// save uploaded file to a defined location on the server | ||||||
|  | 	static String saveFile(final InputStream uploadedInputStream, final String serverLocation) throws FailException { | ||||||
|  | 		String out = ""; | ||||||
|  | 		MessageDigest md = null; | ||||||
|  | 		try (OutputStream outpuStream = new FileOutputStream(new File(serverLocation))) { | ||||||
|  | 			md = MessageDigest.getInstance("SHA-512"); | ||||||
|  | 			outpuStream.flush(); | ||||||
|  | 		} catch (final IOException ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Can not write in temporary file", ex); | ||||||
|  | 		} catch (final NoSuchAlgorithmException ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Can not find sha512 algorithms", ex); | ||||||
|  | 		} | ||||||
|  | 		if (md != null) { | ||||||
|  | 			try (OutputStream outpuStream = new FileOutputStream(new File(serverLocation))) { | ||||||
|  | 				int read = 0; | ||||||
|  | 				final byte[] bytes = new byte[CHUNK_SIZE_IN]; | ||||||
|  | 				while ((read = uploadedInputStream.read(bytes)) != -1) { | ||||||
|  | 					// logger.info("write {}", read); | ||||||
|  | 					md.update(bytes, 0, read); | ||||||
|  | 					outpuStream.write(bytes, 0, read); | ||||||
|  | 				} | ||||||
|  | 				LOGGER.info("Flush input stream ... {}", serverLocation); | ||||||
|  | 				outpuStream.flush(); | ||||||
|  | 				// create the end of sha512 | ||||||
|  | 				final byte[] sha512Digest = md.digest(); | ||||||
|  | 				// convert in hexadecimal | ||||||
|  | 				out = bytesToHex(sha512Digest); | ||||||
|  | 				uploadedInputStream.close(); | ||||||
|  | 			} catch (final IOException ex) { | ||||||
|  | 				throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Can not write in temporary file", ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String bytesToHex(final byte[] bytes) { | ||||||
|  | 		final StringBuilder sb = new StringBuilder(); | ||||||
|  | 		for (final byte b : bytes) { | ||||||
|  | 			sb.append(String.format("%02x", b)); | ||||||
|  | 		} | ||||||
|  | 		return sb.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Data getSmall(final ObjectId oid) { | ||||||
|  | 		try { | ||||||
|  | 			return DataAccess.get(Data.class, oid); | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@POST | ||||||
|  | 	@Path("/upload/") | ||||||
|  | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Insert a new data in the data environment", tags = "SYSTEM") | ||||||
|  | 	public void uploadFile(@Context final SecurityContext sc, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) | ||||||
|  | 			throws FailException { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		LOGGER.info("==================================================="); | ||||||
|  | 		LOGGER.info("== DATA uploadFile {}", (gc == null ? "null" : gc.userByToken)); | ||||||
|  | 		LOGGER.info("==================================================="); | ||||||
|  | 		// public NodeSmall uploadFile(final FormDataMultiPart form) { | ||||||
|  | 		LOGGER.info("Upload file: "); | ||||||
|  | 		final String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId++; | ||||||
|  | 		try { | ||||||
|  | 			createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator); | ||||||
|  | 		} catch (final IOException ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Impossible to create the folder in the server", ex); | ||||||
|  | 		} | ||||||
|  | 		saveFile(fileInputStream, filePath); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@PermitTokenInURI | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get back some data from the data environment", tags = "SYSTEM") | ||||||
|  | 	public Response retrieveDataId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | ||||||
|  | 			@PathParam("oid") final ObjectId oid) throws FailException { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		// logger.info("==================================================="); | ||||||
|  | 		LOGGER.info("== DATA retrieveDataId ? oid={} user={}", oid, (gc == null ? "null" : gc.userByToken)); | ||||||
|  | 		// logger.info("==================================================="); | ||||||
|  | 		final Data value = getSmall(oid); | ||||||
|  | 		if (value == null) { | ||||||
|  | 			return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			return buildStream(getFileData(oid), range, value.mimeType == null ? "application/octet-stream" : value.mimeType); | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to build output stream", ex); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("thumbnail/{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@PermitTokenInURI | ||||||
|  | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get a thumbnail of from the data environment (if resize is possible)", tags = "SYSTEM") | ||||||
|  | 	// @CacheMaxAge(time = 10, unit = TimeUnit.DAYS) | ||||||
|  | 	public Response retrieveDataThumbnailId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | ||||||
|  | 			@PathParam("oid") final ObjectId oid) throws FailException { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		LOGGER.info("==================================================="); | ||||||
|  | 		LOGGER.info("== DATA retrieveDataThumbnailId ? {}", (gc == null ? "null" : gc.userByToken)); | ||||||
|  | 		LOGGER.info("==================================================="); | ||||||
|  | 		final Data value = getSmall(oid); | ||||||
|  | 		if (value == null) { | ||||||
|  | 			return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); | ||||||
|  | 		} | ||||||
|  | 		final String filePathName = getFileData(oid); | ||||||
|  | 		final File inputFile = new File(filePathName); | ||||||
|  | 		if (!inputFile.exists()) { | ||||||
|  | 			return Response.status(404).entity("{\"error\":\"media Does not exist: " + oid + "\"}").type("application/json").build(); | ||||||
|  | 		} | ||||||
|  | 		if (value.mimeType.contentEquals("image/jpeg") || value.mimeType.contentEquals("image/png") | ||||||
|  | 		// || value.mimeType.contentEquals("image/webp") | ||||||
|  | 		) { | ||||||
|  | 			// reads input image | ||||||
|  | 			BufferedImage inputImage; | ||||||
|  | 			try { | ||||||
|  | 				inputImage = ImageIO.read(inputFile); | ||||||
|  | 			} catch (final IOException ex) { | ||||||
|  | 				throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to READ the image", ex); | ||||||
|  | 			} | ||||||
|  | 			LOGGER.info("input size image: {}x{} type={}", inputImage.getWidth(), inputImage.getHeight(), inputImage.getType()); | ||||||
|  | 			final int scaledWidth = ConfigBaseVariable.getThumbnailWidth(); | ||||||
|  | 			final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() * scaledWidth); | ||||||
|  | 			// creates output image | ||||||
|  | 			final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType()); | ||||||
|  |  | ||||||
|  | 			// scales the input image to the output image | ||||||
|  | 			final Graphics2D g2d = outputImage.createGraphics(); | ||||||
|  | 			LOGGER.info("output size image: {}x{}", scaledWidth, scaledHeight); | ||||||
|  | 			g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null); | ||||||
|  | 			g2d.dispose(); | ||||||
|  | 			// create the output stream: | ||||||
|  | 			final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||||
|  | 			try { | ||||||
|  | 				ImageIO.write(outputImage, ConfigBaseVariable.getThumbnailFormat(), baos); | ||||||
|  | 			} catch (final IOException e) { | ||||||
|  | 				e.printStackTrace(); | ||||||
|  | 				return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain").build(); | ||||||
|  | 			} | ||||||
|  | 			final byte[] imageData = baos.toByteArray(); | ||||||
|  | 			LOGGER.info("output length {}", imageData.length); | ||||||
|  | 			if (imageData.length == 0) { | ||||||
|  | 				LOGGER.error("Fail to convert image... Availlable format:"); | ||||||
|  | 				for (final String data : ImageIO.getWriterFormatNames()) { | ||||||
|  | 					LOGGER.error("    - {}", data); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, imageData.length); | ||||||
|  | 			try { | ||||||
|  | 				out.type(getMimeType(ConfigBaseVariable.getThumbnailFormat())); | ||||||
|  | 			} catch (final IOException ex) { | ||||||
|  | 				throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to convert mime type of " + ConfigBaseVariable.getThumbnailFormat(), ex); | ||||||
|  | 			} | ||||||
|  | 			// TODO: move this in a decorator !!! | ||||||
|  | 			final CacheControl cc = new CacheControl(); | ||||||
|  | 			cc.setMaxAge(3600); | ||||||
|  | 			cc.setNoCache(false); | ||||||
|  | 			out.cacheControl(cc); | ||||||
|  | 			return out.build(); | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			return buildStream(filePathName, range, value.mimeType); | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to build output stream", ex); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}/{name}") | ||||||
|  | 	@PermitTokenInURI | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get back some data from the data environment (with a beautiful name (permit download with basic name)", tags = "SYSTEM") | ||||||
|  | 	public Response retrieveDataFull(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @ApiInputOptional @HeaderParam("Range") final String range, | ||||||
|  | 			@PathParam("oid") final ObjectId oid, @PathParam("name") final String name) throws Exception { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		// logger.info("==================================================="); | ||||||
|  | 		LOGGER.info("== DATA retrieveDataFull ? id={} user={}", oid, (gc == null ? "null" : gc.userByToken)); | ||||||
|  | 		// logger.info("==================================================="); | ||||||
|  | 		final Data value = getSmall(oid); | ||||||
|  | 		if (value == null) { | ||||||
|  | 			return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); | ||||||
|  | 		} | ||||||
|  | 		return buildStream(getFileData(oid), range, value.mimeType == null ? "application/octet-stream" : value.mimeType); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** Adapted from http://stackoverflow.com/questions/12768812/video-streaming-to-ipad-does-not-work-with-tapestry5/12829541#12829541 | ||||||
|  | 	 * | ||||||
|  | 	 * @param range range header | ||||||
|  | 	 * @return Streaming output | ||||||
|  | 	 * @throws FileNotFoundException | ||||||
|  | 	 * @throws Exception IOException if an error occurs in streaming. */ | ||||||
|  | 	private Response buildStream(final String filename, final String range, final String mimeType) throws FailException { | ||||||
|  | 		final File file = new File(filename); | ||||||
|  | 		// logger.info("request range : {}", range); | ||||||
|  | 		// range not requested : Firefox does not send range headers | ||||||
|  | 		if (range == null) { | ||||||
|  | 			final StreamingOutput output = new StreamingOutput() { | ||||||
|  | 				@Override | ||||||
|  | 				public void write(final OutputStream out) { | ||||||
|  | 					try (FileInputStream in = new FileInputStream(file)) { | ||||||
|  | 						final byte[] buf = new byte[1024 * 1024]; | ||||||
|  | 						int len; | ||||||
|  | 						while ((len = in.read(buf)) != -1) { | ||||||
|  | 							try { | ||||||
|  | 								out.write(buf, 0, len); | ||||||
|  | 								out.flush(); | ||||||
|  | 								// logger.info("---- wrote {} bytes file ----", len); | ||||||
|  | 							} catch (final IOException ex) { | ||||||
|  | 								LOGGER.info("remote close connection"); | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} catch (final IOException ex) { | ||||||
|  | 						throw new InternalServerErrorException(ex); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 			final Response.ResponseBuilder out = Response.ok(output).header(HttpHeaders.CONTENT_LENGTH, file.length()); | ||||||
|  | 			if (mimeType != null) { | ||||||
|  | 				out.type(mimeType); | ||||||
|  | 			} | ||||||
|  | 			return out.build(); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		final String[] ranges = range.split("=")[1].split("-"); | ||||||
|  | 		final long from = Long.parseLong(ranges[0]); | ||||||
|  |  | ||||||
|  | 		// logger.info("request range : {}", ranges.length); | ||||||
|  | 		// Chunk media if the range upper bound is unspecified. Chrome, Opera sends "bytes=0-" | ||||||
|  | 		long to = CHUNK_SIZE + from; | ||||||
|  | 		if (ranges.length == 1) { | ||||||
|  | 			to = file.length() - 1; | ||||||
|  | 		} else if (to >= file.length()) { | ||||||
|  | 			to = file.length() - 1; | ||||||
|  | 		} | ||||||
|  | 		final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length()); | ||||||
|  | 		// LOGGER.info("responseRange: {}", responseRange); | ||||||
|  | 		try { | ||||||
|  | 			final RandomAccessFile raf = new RandomAccessFile(file, "r"); | ||||||
|  | 			raf.seek(from); | ||||||
|  |  | ||||||
|  | 			final long len = to - from + 1; | ||||||
|  | 			final MediaStreamer streamer = new MediaStreamer(len, raf); | ||||||
|  | 			final Response.ResponseBuilder out = Response.ok(streamer).status(Response.Status.PARTIAL_CONTENT).header("Accept-Ranges", "bytes").header("Content-Range", responseRange) | ||||||
|  | 					.header(HttpHeaders.CONTENT_LENGTH, streamer.getLenth()).header(HttpHeaders.LAST_MODIFIED, new Date(file.lastModified())); | ||||||
|  | 			if (mimeType != null) { | ||||||
|  | 				out.type(mimeType); | ||||||
|  | 			} | ||||||
|  | 			return out.build(); | ||||||
|  | 		} catch (final FileNotFoundException ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to find the required file.", ex); | ||||||
|  | 		} catch (final IOException ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to access to the required file.", ex); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void undelete(final Long id) throws Exception { | ||||||
|  | 		DataAccess.unsetDelete(Data.class, id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,11 +1,10 @@ | |||||||
| package org.kar.karideo.api; | package org.atriasoft.karideo.api; | ||||||
| 
 | 
 | ||||||
| 
 | import org.atriasoft.archidata.api.FrontGeneric; | ||||||
| import org.kar.archidata.api.FrontGeneric; |  | ||||||
| 
 | 
 | ||||||
| import jakarta.ws.rs.Path; | import jakarta.ws.rs.Path; | ||||||
| 
 | 
 | ||||||
| import org.kar.karideo.util.ConfigVariable; | import org.atriasoft.karideo.util.ConfigVariable; | ||||||
| 
 | 
 | ||||||
| @Path("/front") | @Path("/front") | ||||||
| public class Front extends FrontGeneric { | public class Front extends FrontGeneric { | ||||||
| @@ -1,11 +1,12 @@ | |||||||
| package org.kar.karideo.api; | package org.atriasoft.karideo.api; | ||||||
| 
 | 
 | ||||||
| import org.kar.archidata.exception.FailException; | import org.atriasoft.archidata.exception.FailException; | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
| import org.kar.archidata.tools.JWTWrapper; | import org.atriasoft.archidata.tools.JWTWrapper; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import jakarta.annotation.security.PermitAll; | import jakarta.annotation.security.PermitAll; | ||||||
| import jakarta.ws.rs.GET; | import jakarta.ws.rs.GET; | ||||||
| import jakarta.ws.rs.Path; | import jakarta.ws.rs.Path; | ||||||
| @@ -18,11 +19,13 @@ import jakarta.ws.rs.core.Response; | |||||||
| public class HealthCheck { | public class HealthCheck { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(HealthCheck.class); | ||||||
| 
 | 
 | ||||||
| 	public record HealthResult( | 	public record HealthResult(String value) { | ||||||
| 			String value) {}; | 
 | ||||||
|  | 	}; | ||||||
| 
 | 
 | ||||||
| 	@GET | 	@GET | ||||||
| 	@PermitAll | 	@PermitAll | ||||||
|  | 	@Operation(description = "Get the server state (health)", tags = "SYSTEM") | ||||||
| 	public HealthResult getHealth() throws FailException { | 	public HealthResult getHealth() throws FailException { | ||||||
| 		if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) { | 		if (JWTWrapper.getPublicKeyJson() == null && !ConfigBaseVariable.getTestMode()) { | ||||||
| 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token"); | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Missing Jwt public token"); | ||||||
							
								
								
									
										241
									
								
								back/src/org/atriasoft/karideo/api/MediaResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								back/src/org/atriasoft/karideo/api/MediaResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.sql.SQLException; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.apiGenerator.ApiTypeScriptProgress; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupUpdate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.ValidGroup; | ||||||
|  | import org.atriasoft.archidata.api.DataResource; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DBAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.exception.FailException; | ||||||
|  | import org.atriasoft.archidata.exception.InputException; | ||||||
|  | import org.atriasoft.archidata.model.Data; | ||||||
|  | import org.atriasoft.archidata.tools.DataTools; | ||||||
|  | import org.atriasoft.karideo.model.Media; | ||||||
|  | import org.atriasoft.karideo.model.Season; | ||||||
|  | import org.atriasoft.karideo.model.Series; | ||||||
|  | import org.atriasoft.karideo.model.Type; | ||||||
|  | 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 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.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("/media") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class MediaResource { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(MediaResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get all Media", tags = "GLOBAL") | ||||||
|  | 	public List<Media> gets() throws Exception { | ||||||
|  | 		return DataAccess.gets(Media.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{id}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get a specific Media with his ID", tags = "GLOBAL") | ||||||
|  | 	public Media get(@PathParam("id") final Long id) throws Exception { | ||||||
|  | 		return DataAccess.get(Media.class, id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@PUT | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Modify a specific Media", tags = "GLOBAL") | ||||||
|  | 	public Media put(@PathParam("oid") final ObjectId oid, @Valid @ValidGroup(GroupUpdate.class) final Media media) throws Exception { | ||||||
|  | 		LOGGER.info("update video {} ==> '{}'", oid, media); | ||||||
|  | 		media.oid = oid; | ||||||
|  | 		DataAccess.update(media, oid); | ||||||
|  | 		return DataAccess.get(Media.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private String multipartCorrection(final String data) { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (data.isEmpty()) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (data.contentEquals("null")) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (data.contentEquals("undefined")) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		return data; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@POST | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
|  | 	@Operation(description = "Create a new Media", tags = "GLOBAL") | ||||||
|  | 	@ApiTypeScriptProgress | ||||||
|  | 	public Media uploadMedia( // | ||||||
|  | 			// @AsyncType(Long.class) @FormDataParam("universeId") String universeId, // | ||||||
|  | 			// @AsyncType(Long.class) @FormDataParam("typeId") String typeId, // | ||||||
|  | 			// @AsyncType(Long.class) @FormDataParam("seriesId") String seriesId, // | ||||||
|  | 			// @AsyncType(Long.class) @FormDataParam("season") String season, // value of the season ==> local add if needed | ||||||
|  | 			// @AsyncType(Long.class) @FormDataParam("episode") String episode, // value of the season ==> local add if needed | ||||||
|  | 			@FormDataParam("universeId") String universeId, // | ||||||
|  | 			@FormDataParam("typeId") String typeId, // | ||||||
|  | 			@FormDataParam("seriesId") String seriesId, // | ||||||
|  | 			@FormDataParam("season") String season, // value of the season ==> local add if needed | ||||||
|  | 			@FormDataParam("episode") String episode, // value of the season ==> local add if needed | ||||||
|  | 			@FormDataParam("title") String title, // | ||||||
|  | 			@FormDataParam("file") final InputStream fileInputStream, // | ||||||
|  | 			@FormDataParam("file") final FormDataContentDisposition fileMetaData // | ||||||
|  | 	) throws FailException { | ||||||
|  | 		try (DBAccess db = DBAccess.createInterface()) { | ||||||
|  | 			// correct input string stream : | ||||||
|  | 			final String fileName = multipartCorrection(fileMetaData.getFileName()); | ||||||
|  | 			universeId = multipartCorrection(universeId); | ||||||
|  | 			final ObjectId universeOid = universeId != null ? new ObjectId(universeId) : null; | ||||||
|  | 			typeId = multipartCorrection(typeId); | ||||||
|  | 			final ObjectId typeOid = typeId != null ? new ObjectId(typeId) : null; | ||||||
|  | 			seriesId = multipartCorrection(seriesId); | ||||||
|  | 			final ObjectId seriesOid = seriesId != null ? new ObjectId(seriesId) : null; | ||||||
|  | 			season = multipartCorrection(season); | ||||||
|  | 			final Long seasonLong = season != null ? Long.parseLong(season) : null; | ||||||
|  | 			episode = multipartCorrection(episode); | ||||||
|  | 			title = multipartCorrection(title); | ||||||
|  |  | ||||||
|  | 			// todo: check if all remotes Id exist ... | ||||||
|  |  | ||||||
|  | 			// public NodeSmall uploadFile(final FormDataMultiPart form) { | ||||||
|  | 			LOGGER.info("Upload media file: {}", fileMetaData); | ||||||
|  | 			LOGGER.info("    - fileName: {}", fileName); | ||||||
|  | 			LOGGER.info("    - universe: {}", universeOid); | ||||||
|  | 			LOGGER.info("    - series: {}", seriesOid); | ||||||
|  | 			LOGGER.info("    - season: {}", seasonLong); | ||||||
|  | 			LOGGER.info("    - episode: {}", episode); | ||||||
|  | 			LOGGER.info("    - title: {}", title); | ||||||
|  | 			LOGGER.info("    - type: {}", typeId); | ||||||
|  | 			LOGGER.info("    - fileInputStream: {}", fileInputStream); | ||||||
|  | 			LOGGER.info("    - fileMetaData: {}", fileMetaData); | ||||||
|  | 			System.out.flush(); | ||||||
|  | 			if (typeId == null) { | ||||||
|  | 				throw new InputException("typeId", "TypiId is not specified"); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			final long tmpUID = DataResource.getTmpDataId(); | ||||||
|  | 			final String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID); | ||||||
|  | 			Data data = DataTools.getWithSha512(db, sha512); | ||||||
|  | 			if (data == null) { | ||||||
|  | 				LOGGER.info("Need to add the data in the BDD ... "); | ||||||
|  | 				System.out.flush(); | ||||||
|  | 				try { | ||||||
|  | 					data = DataTools.createNewData(db, tmpUID, fileName, sha512); | ||||||
|  | 				} catch (final IOException ex) { | ||||||
|  | 					DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 					ex.printStackTrace(); | ||||||
|  | 					throw new FailException("can not create input media (the data model has an internal error"); | ||||||
|  | 				} | ||||||
|  | 			} else if (data != null && data.deleted != null && data.deleted) { | ||||||
|  | 				LOGGER.info("Data already exist but deleted"); | ||||||
|  | 				System.out.flush(); | ||||||
|  | 				DataTools.undelete(db, data.oid); | ||||||
|  | 				data.deleted = false; | ||||||
|  | 			} else { | ||||||
|  | 				LOGGER.info("Data already exist ... all good"); | ||||||
|  | 				System.out.flush(); | ||||||
|  | 			} | ||||||
|  | 			// Fist step: retieve all the Id of each parents:... | ||||||
|  | 			LOGGER.info("Find typeNode"); | ||||||
|  | 			// check if id of type exist: | ||||||
|  | 			final Type typeNode = TypeResource.getId(typeOid); | ||||||
|  | 			if (typeNode == null) { | ||||||
|  | 				DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 				throw new InputException("typeId", "TypeId does not exist ..."); | ||||||
|  | 			} | ||||||
|  | 			// check if id of type exist: | ||||||
|  | 			Series seriesNode = null; | ||||||
|  | 			if (seriesOid != null) { | ||||||
|  | 				seriesNode = SeriesResource.getId(seriesOid); | ||||||
|  | 				if (seriesNode == null) { | ||||||
|  | 					DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 					throw new InputException("seriesId", "seriesId does not exist ..."); | ||||||
|  | 				} | ||||||
|  | 				if (!seriesNode.typeId.equals(typeNode.oid)) { | ||||||
|  | 					DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 					throw new InputException("seriesId", "seriesId object have not the correct parent... '" + seriesNode.typeId + "' != '" + typeNode.oid + "'"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			LOGGER.info("    ==> {}", seriesNode); | ||||||
|  | 			LOGGER.info("Find seasonNode"); | ||||||
|  | 			// get uid of season: | ||||||
|  | 			Season seasonNode = null; | ||||||
|  | 			if (seriesNode == null && seasonLong != null) { | ||||||
|  | 				DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 				throw new InputException("season", "Season is set but no series is set !!"); | ||||||
|  | 			} | ||||||
|  | 			if (season != null) { | ||||||
|  | 				seasonNode = SeasonResource.getOrCreate(season, seriesNode.oid); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			LOGGER.info("    ==> {}", seasonNode); | ||||||
|  | 			LOGGER.info("add media"); | ||||||
|  |  | ||||||
|  | 			try { | ||||||
|  | 				final Media media = new Media(); | ||||||
|  | 				media.name = title; | ||||||
|  | 				media.dataId = data.oid; | ||||||
|  | 				media.typeId = typeNode.oid; | ||||||
|  | 				media.seriesId = null; | ||||||
|  | 				if (seriesNode != null) { | ||||||
|  | 					media.seriesId = seriesNode.oid; | ||||||
|  | 				} | ||||||
|  | 				media.seasonId = null; | ||||||
|  | 				if (seasonNode != null) { | ||||||
|  | 					media.seasonId = seasonNode.oid; | ||||||
|  | 				} | ||||||
|  | 				media.episode = null; | ||||||
|  | 				if (episode != null && !episode.contentEquals("")) { | ||||||
|  | 					media.episode = Integer.parseInt(episode); | ||||||
|  | 				} | ||||||
|  | 				final Media out = db.insert(media); | ||||||
|  | 				LOGGER.info("Generate new media {}", out); | ||||||
|  | 				return out; | ||||||
|  | 			} catch (final SQLException ex) { | ||||||
|  | 				ex.printStackTrace(); | ||||||
|  | 				LOGGER.error("Catch error: {}", ex.getMessage()); | ||||||
|  | 				throw new FailException("Catch SQLerror ==> check server logs"); | ||||||
|  | 			} finally { | ||||||
|  | 				DataResource.removeTemporaryFile(tmpUID); | ||||||
|  | 			} | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			LOGGER.error("Catch an unexpected error ... {} ", ex.getMessage()); | ||||||
|  | 			ex.printStackTrace(); | ||||||
|  | 			throw new FailException("Catch Exception ==> check server logs"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@DELETE | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Remove a specific Media", tags = "GLOBAL") | ||||||
|  | 	public void remove(@PathParam("oid") final ObjectId id) throws Exception { | ||||||
|  | 		DataAccess.delete(Media.class, id); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								back/src/org/atriasoft/karideo/api/SeasonResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								back/src/org/atriasoft/karideo/api/SeasonResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupCreate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupUpdate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.ValidGroup; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryAnd; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.Condition; | ||||||
|  | import org.atriasoft.karideo.model.Season; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | 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.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("/season") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class SeasonResource { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(SeasonResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get a specific Season with his ID", tags = "GLOBAL") | ||||||
|  | 	public List<Season> gets() throws Exception { | ||||||
|  | 		return DataAccess.gets(Season.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Get all season", tags = "GLOBAL") | ||||||
|  | 	public Season get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		return DataAccess.get(Season.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* ============================================================================= ADMIN SECTION: ============================================================================= */ | ||||||
|  |  | ||||||
|  | 	@POST | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Create a new season", tags = "GLOBAL") | ||||||
|  | 	public Season post(@Valid @ValidGroup(GroupCreate.class) final Season season) throws Exception { | ||||||
|  | 		return DataAccess.insert(season); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@PUT | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Modify a specific season", tags = "GLOBAL") | ||||||
|  | 	public Season put(@PathParam("oid") final ObjectId oid, @Valid @ValidGroup(GroupUpdate.class) final Season season) throws Exception { | ||||||
|  | 		season.oid = oid; | ||||||
|  | 		DataAccess.update(season, oid); | ||||||
|  | 		return DataAccess.get(Season.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@DELETE | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Remove a specific season", tags = "GLOBAL") | ||||||
|  | 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		DataAccess.delete(Season.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Season getOrCreate(final String name, final ObjectId seriesId) { | ||||||
|  | 		try { | ||||||
|  | 			Season out = DataAccess.getWhere(Season.class, new Condition(new QueryAnd(new QueryCondition("name", "=", name), new QueryCondition("seriesId", "=", seriesId)))); | ||||||
|  | 			if (out == null) { | ||||||
|  | 				out = new Season(); | ||||||
|  | 				out.name = name; | ||||||
|  | 				out.seriesId = seriesId; | ||||||
|  | 				out = DataAccess.insert(out); | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								back/src/org/atriasoft/karideo/api/SeriesResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								back/src/org/atriasoft/karideo/api/SeriesResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupCreate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupUpdate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.ValidGroup; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryAnd; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.Condition; | ||||||
|  | import org.atriasoft.karideo.model.Series; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | 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.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("/series") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class SeriesResource { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get all Series", tags = "GLOBAL") | ||||||
|  | 	public List<Series> gets() throws Exception { | ||||||
|  | 		return DataAccess.gets(Series.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Get a specific Series with his ID", tags = "GLOBAL") | ||||||
|  | 	public Series get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		return DataAccess.get(Series.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Series getId(final ObjectId oid) throws Exception { | ||||||
|  | 		return DataAccess.get(Series.class, oid); | ||||||
|  | 	} | ||||||
|  | 	/* ============================================================================= ADMIN SECTION: ============================================================================= */ | ||||||
|  |  | ||||||
|  | 	@POST | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Create a new Series", tags = "GLOBAL") | ||||||
|  | 	public Series post(@Valid @ValidGroup(GroupCreate.class) final Series jsonRequest) throws Exception { | ||||||
|  | 		return DataAccess.insert(jsonRequest); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@PUT | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Modify a specific Series", tags = "GLOBAL") | ||||||
|  | 	public Series put(@PathParam("oid") final ObjectId oid, @Valid @ValidGroup(GroupUpdate.class) final Series series) throws Exception { | ||||||
|  | 		series.oid = oid; | ||||||
|  | 		DataAccess.update(series, oid); | ||||||
|  | 		return DataAccess.get(Series.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@DELETE | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Remove a specific Series", tags = "GLOBAL") | ||||||
|  | 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		DataAccess.delete(Series.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Series getOrCreate(final String name, final ObjectId typeId) { | ||||||
|  | 		try { | ||||||
|  | 			Series out = DataAccess.getWhere(Series.class, new Condition(new QueryAnd(new QueryCondition("name", "=", name), new QueryCondition("typeId", "=", typeId)))); | ||||||
|  | 			if (out == null) { | ||||||
|  | 				out = new Series(); | ||||||
|  | 				out.name = name; | ||||||
|  | 				out.typeId = typeId; | ||||||
|  | 				out = DataAccess.insert(out); | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										99
									
								
								back/src/org/atriasoft/karideo/api/TypeResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								back/src/org/atriasoft/karideo/api/TypeResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupCreate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupUpdate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.ValidGroup; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.Condition; | ||||||
|  | import org.atriasoft.karideo.model.Type; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | 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.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("/type") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class TypeResource { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(TypeResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get all Type", tags = "GLOBAL") | ||||||
|  | 	public List<Type> gets() throws Exception { | ||||||
|  | 		return DataAccess.gets(Type.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Get a specific Type with his ID", tags = "GLOBAL") | ||||||
|  | 	public Type get(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		return DataAccess.get(Type.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Type getId(final ObjectId oid) throws Exception { | ||||||
|  | 		return DataAccess.get(Type.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* ============================================================================= ADMIN SECTION: ============================================================================= */ | ||||||
|  |  | ||||||
|  | 	@POST | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Create a new Type", tags = "GLOBAL") | ||||||
|  | 	public Type post(@Valid @ValidGroup(GroupCreate.class) final Type jsonRequest) throws Exception { | ||||||
|  | 		return DataAccess.insert(jsonRequest); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@PUT | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Modify a specific Type", tags = "GLOBAL") | ||||||
|  | 	public Type patch(@PathParam("oid") final ObjectId oid, @Valid @ValidGroup(GroupUpdate.class) final Type type) throws Exception { | ||||||
|  | 		type.oid = oid; | ||||||
|  | 		DataAccess.update(type, oid); | ||||||
|  | 		return DataAccess.get(Type.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@DELETE | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Remove a specific Type", tags = "GLOBAL") | ||||||
|  | 	public void remove(@PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		DataAccess.delete(Type.class, oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Type getOrCreate(final String name) { | ||||||
|  | 		try { | ||||||
|  | 			Type out = DataAccess.getWhere(Type.class, new Condition(new QueryCondition("name", "=", name))); | ||||||
|  | 			if (out == null) { | ||||||
|  | 				out = new Type(); | ||||||
|  | 				out.name = name; | ||||||
|  | 				out = DataAccess.insert(out); | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,111 @@ | |||||||
|  | package org.atriasoft.karideo.api; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.checker.GroupUpdate; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.ValidGroup; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryAnd; | ||||||
|  | import org.atriasoft.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.Condition; | ||||||
|  | import org.atriasoft.archidata.dataAccess.options.FilterValue; | ||||||
|  | import org.atriasoft.archidata.filter.GenericContext; | ||||||
|  | import org.atriasoft.karideo.model.UserMediaAdvancement; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | 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.PUT; | ||||||
|  | import jakarta.ws.rs.Path; | ||||||
|  | import jakarta.ws.rs.PathParam; | ||||||
|  | import jakarta.ws.rs.Produces; | ||||||
|  | import jakarta.ws.rs.core.Context; | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.SecurityContext; | ||||||
|  |  | ||||||
|  | @Path("/advancement") | ||||||
|  | @Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class UserMediaAdvancementResource { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(UserMediaAdvancementResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get a specific user advancement with his ID", tags = "GLOBAL") | ||||||
|  | 	public UserMediaAdvancement get(@Context final SecurityContext sc, @PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		return DataAccess.getWhere(UserMediaAdvancement.class, new Condition(new QueryAnd(new QueryCondition("mediaId", "=", oid), new QueryCondition("userId", "=", gc.userByToken.oid)))); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get all user advancement", tags = "GLOBAL") | ||||||
|  | 	public List<UserMediaAdvancement> gets(@Context final SecurityContext sc) throws Exception { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		return DataAccess.getsWhere(UserMediaAdvancement.class, new Condition(new QueryCondition("userId", "=", gc.userByToken.oid))); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* ============================================================================= Modification SECTION: ============================================================================= */ | ||||||
|  |  | ||||||
|  | 	public record MediaInformations(int time, float percent, int count) { | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// @POST | ||||||
|  | 	// @Path("{id}") | ||||||
|  | 	// @RolesAllowed("USER") | ||||||
|  | 	// @Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	public UserMediaAdvancement post(@Context final SecurityContext sc, @PathParam("oid") final ObjectId oid, final MediaInformations data) throws Exception { | ||||||
|  | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|  | 		final UserMediaAdvancement elem = new UserMediaAdvancement(); | ||||||
|  | 		elem.userId = gc.userByToken.oid; | ||||||
|  | 		elem.mediaId = oid; | ||||||
|  | 		elem.time = data.time; | ||||||
|  | 		elem.percent = data.percent; | ||||||
|  | 		elem.count = data.count; | ||||||
|  | 		return DataAccess.insert(elem); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public record MediaInformationsDelta(int time, float percent, boolean addCount) { | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@PUT | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Consumes(MediaType.APPLICATION_JSON) | ||||||
|  | 	@Operation(description = "Modify a user advancement", tags = "GLOBAL") | ||||||
|  | 	public UserMediaAdvancement put(@Context final SecurityContext sc, @PathParam("oid") final ObjectId oid, @Valid @ValidGroup(GroupUpdate.class) final MediaInformationsDelta data) throws Exception { | ||||||
|  | 		final UserMediaAdvancement elem = get(sc, oid); | ||||||
|  | 		if (elem == null) { | ||||||
|  | 			// insert element | ||||||
|  | 			if (data.addCount) { | ||||||
|  | 				return post(sc, oid, new MediaInformations(data.time(), data.percent(), 1)); | ||||||
|  | 			} else { | ||||||
|  | 				return post(sc, oid, new MediaInformations(data.time(), data.percent(), 0)); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		elem.time = data.time; | ||||||
|  | 		elem.percent = data.percent; | ||||||
|  | 		if (data.addCount) { | ||||||
|  | 			elem.count++; | ||||||
|  | 		} | ||||||
|  | 		LOGGER.info("{},{},{}", elem.time, elem.percent, elem.count); | ||||||
|  | 		DataAccess.update(elem, elem.oid, new FilterValue("time", "percent", "count")); | ||||||
|  | 		return DataAccess.get(UserMediaAdvancement.class, elem.oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@DELETE | ||||||
|  | 	@Path("{oid}") | ||||||
|  | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Remove a specific user advancement", tags = "GLOBAL") | ||||||
|  | 	public void remove(@Context final SecurityContext sc, @PathParam("oid") final ObjectId oid) throws Exception { | ||||||
|  | 		final UserMediaAdvancement elem = get(sc, oid); | ||||||
|  | 		DataAccess.delete(UserMediaAdvancement.class, elem.oid); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,15 +1,17 @@ | |||||||
| package org.kar.karideo.api; | package org.atriasoft.karideo.api; | ||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.atriasoft.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.filter.GenericContext; | import org.atriasoft.archidata.filter.GenericContext; | ||||||
| import org.kar.karideo.model.UserKarideo; | import org.atriasoft.karideo.model.UserKarideo; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
| 
 | 
 | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import jakarta.annotation.security.RolesAllowed; | import jakarta.annotation.security.RolesAllowed; | ||||||
| import jakarta.ws.rs.GET; | import jakarta.ws.rs.GET; | ||||||
| import jakarta.ws.rs.Path; | import jakarta.ws.rs.Path; | ||||||
| @@ -20,17 +22,17 @@ import jakarta.ws.rs.core.MediaType; | |||||||
| import jakarta.ws.rs.core.SecurityContext; | import jakarta.ws.rs.core.SecurityContext; | ||||||
| 
 | 
 | ||||||
| @Path("/users") | @Path("/users") | ||||||
| @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) | @Produces(MediaType.APPLICATION_JSON) | ||||||
| public class UserResource { | public class UserResource { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class); | ||||||
| 
 | 
 | ||||||
| 	@JsonInclude(JsonInclude.Include.NON_NULL) | 	@JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| 	public class UserOut { | 	public class UserOut { | ||||||
| 		public long id; | 		public ObjectId oid; | ||||||
| 		public String login; | 		public String login; | ||||||
| 
 | 
 | ||||||
| 		public UserOut(final long id, final String login) { | 		public UserOut(final ObjectId oid, final String login) { | ||||||
| 			this.id = id; | 			this.oid = oid; | ||||||
| 			this.login = login; | 			this.login = login; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @@ -41,7 +43,8 @@ public class UserResource { | |||||||
| 	// curl http://localhost:9993/api/users | 	// curl http://localhost:9993/api/users | ||||||
| 	@GET | 	@GET | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	public List<UserKarideo> getUsers() { | 	@Operation(description = "Get all the users", tags = "SYSTEM") | ||||||
|  | 	public List<UserKarideo> gets() { | ||||||
| 		System.out.println("getUsers"); | 		System.out.println("getUsers"); | ||||||
| 		try { | 		try { | ||||||
| 			return DataAccess.gets(UserKarideo.class); | 			return DataAccess.gets(UserKarideo.class); | ||||||
| @@ -54,9 +57,10 @@ public class UserResource { | |||||||
| 
 | 
 | ||||||
| 	// curl http://localhost:9993/api/users/3 | 	// curl http://localhost:9993/api/users/3 | ||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{id}") | 	@Path("{oid}") | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
| 	public UserKarideo getUsers(@Context final SecurityContext sc, @PathParam("id") final long userId) { | 	@Operation(description = "Get a specific user data", tags = "SYSTEM") | ||||||
|  | 	public UserKarideo get(@Context final SecurityContext sc, @PathParam("oid") final ObjectId userId) { | ||||||
| 		System.out.println("getUser " + userId); | 		System.out.println("getUser " + userId); | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| 		System.out.println("==================================================="); | 		System.out.println("==================================================="); | ||||||
| @@ -74,11 +78,12 @@ public class UserResource { | |||||||
| 	@GET | 	@GET | ||||||
| 	@Path("me") | 	@Path("me") | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
|  | 	@Operation(description = "Get the user personal data", tags = "SYSTEM") | ||||||
| 	public UserOut getMe(@Context final SecurityContext sc) { | 	public UserOut getMe(@Context final SecurityContext sc) { | ||||||
| 		LOGGER.debug("getMe()"); | 		LOGGER.debug("getMe()"); | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| 		LOGGER.debug("== USER ? {}", gc.userByToken); | 		LOGGER.debug("== USER ? {}", gc.userByToken); | ||||||
| 		return new UserOut(gc.userByToken.id, gc.userByToken.name); | 		return new UserOut(gc.userByToken.oid, gc.userByToken.name); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| package org.kar.karideo.filter; | package org.atriasoft.karideo.filter; | ||||||
| 
 | 
 | ||||||
| import org.kar.archidata.filter.AuthenticationFilter; | import org.atriasoft.archidata.filter.AuthenticationFilter; | ||||||
| 
 | 
 | ||||||
| import jakarta.ws.rs.Priorities; | import jakarta.ws.rs.Priorities; | ||||||
| import jakarta.ws.rs.ext.Provider; | import jakarta.ws.rs.ext.Provider; | ||||||
| @@ -16,7 +16,7 @@ import jakarta.annotation.Priority; | |||||||
| public class KarideoAuthenticationFilter extends AuthenticationFilter { | public class KarideoAuthenticationFilter extends AuthenticationFilter { | ||||||
| 	final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class); | 	final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class); | ||||||
| 
 | 
 | ||||||
|     public KarideoAuthenticationFilter() { | 	public KarideoAuthenticationFilter() { | ||||||
| 		super("karideo"); | 		super("karideo"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
							
								
								
									
										60
									
								
								back/src/org/atriasoft/karideo/internal/Log.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								back/src/org/atriasoft/karideo/internal/Log.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | package org.atriasoft.karideo.internal; | ||||||
|  |  | ||||||
|  | //import io.scenarium.logger.LogLevel; | ||||||
|  | //import io.scenarium.logger.Logger; | ||||||
|  |  | ||||||
|  | public class Log { | ||||||
|  | 	// private static final String LIB_NAME = "logger"; | ||||||
|  | 	// private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); | ||||||
|  | 	// private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); | ||||||
|  | 	// private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); | ||||||
|  | 	// private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); | ||||||
|  | 	// private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); | ||||||
|  | 	// private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); | ||||||
|  | 	// private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); | ||||||
|  | 	// private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); | ||||||
|  | 	// private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); | ||||||
|  | 	// | ||||||
|  | 	// private Log() {} | ||||||
|  | 	// | ||||||
|  | 	// public static void print(String data) { | ||||||
|  | 	// if (PRINT_PRINT) | ||||||
|  | 	// Logger.print(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void todo(String data) { | ||||||
|  | 	// if (PRINT_TODO) | ||||||
|  | 	// Logger.todo(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void critical(String data) { | ||||||
|  | 	// if (PRINT_CRITICAL) | ||||||
|  | 	// Logger.critical(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void error(String data) { | ||||||
|  | 	// if (PRINT_ERROR) | ||||||
|  | 	// Logger.error(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void warning(String data) { | ||||||
|  | 	// if (PRINT_WARNING) | ||||||
|  | 	// Logger.warning(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void info(String data) { | ||||||
|  | 	// if (PRINT_INFO) | ||||||
|  | 	// Logger.info(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void debug(String data) { | ||||||
|  | 	// if (PRINT_DEBUG) | ||||||
|  | 	// Logger.debug(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  | 	// | ||||||
|  | 	// public static void verbose(String data) { | ||||||
|  | 	// if (PRINT_VERBOSE) | ||||||
|  | 	// Logger.verbose(LIB_NAME_DRAW, data); | ||||||
|  | 	// } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								back/src/org/atriasoft/karideo/job/BackupJob.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								back/src/org/atriasoft/karideo/job/BackupJob.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | package org.atriasoft.karideo.job; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
|  | import java.time.ZonedDateTime; | ||||||
|  | import java.time.format.DateTimeFormatter; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.backup.BackupEngine; | ||||||
|  | import org.atriasoft.archidata.backup.BackupEngine.EngineBackupType; | ||||||
|  | import org.atriasoft.archidata.exception.DataAccessException; | ||||||
|  | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.atriasoft.karideo.migration.Initialization; | ||||||
|  | import org.atriasoft.karideo.util.ConfigVariable; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class BackupJob implements Runnable { | ||||||
|  |  | ||||||
|  | 	final static Logger LOGGER = LoggerFactory.getLogger(BackupJob.class); | ||||||
|  | 	BackupEngine engine; | ||||||
|  |  | ||||||
|  | 	public BackupJob() throws DataAccessException, IOException { | ||||||
|  | 		final Path path = Paths.get(ConfigVariable.getBackupFolder()); | ||||||
|  | 		Files.createDirectories(path); | ||||||
|  | 		this.engine = new BackupEngine(path, ConfigBaseVariable.getDBName(), EngineBackupType.JSON_EXTENDED); | ||||||
|  | 		this.engine.setEnableStoreOrRestoreData(false); | ||||||
|  | 		for (final Class<?> clazz : Initialization.CLASSES_BASE) { | ||||||
|  | 			this.engine.addClass(clazz); | ||||||
|  | 		} | ||||||
|  | 		this.engine.addCollection("counters"); | ||||||
|  | 		this.engine.addCollection("KAR_migration"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void run() { | ||||||
|  | 		LOGGER.warn("Backup request"); | ||||||
|  | 		try { | ||||||
|  | 			final String timestampUtc = ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss.SSS")); | ||||||
|  | 			this.engine.store(timestampUtc + "_full"); | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			LOGGER.error("Fail in Backup: {}", ex.getMessage()); | ||||||
|  | 			ex.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										131
									
								
								back/src/org/atriasoft/karideo/migration/Initialization.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								back/src/org/atriasoft/karideo/migration/Initialization.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | package org.atriasoft.karideo.migration; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.api.DataResource; | ||||||
|  | import org.atriasoft.archidata.backup.BackupEngine; | ||||||
|  | import org.atriasoft.archidata.backup.BackupEngine.EngineBackupType; | ||||||
|  | import org.atriasoft.archidata.dataAccess.DBAccess; | ||||||
|  | import org.atriasoft.archidata.db.DbConfig; | ||||||
|  | import org.atriasoft.archidata.exception.DataAccessException; | ||||||
|  | import org.atriasoft.archidata.exception.FailException; | ||||||
|  | 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.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.atriasoft.karideo.api.Front; | ||||||
|  | import org.atriasoft.karideo.api.HealthCheck; | ||||||
|  | import org.atriasoft.karideo.api.MediaResource; | ||||||
|  | import org.atriasoft.karideo.api.SeasonResource; | ||||||
|  | import org.atriasoft.karideo.api.SeriesResource; | ||||||
|  | import org.atriasoft.karideo.api.TypeResource; | ||||||
|  | import org.atriasoft.karideo.api.UserMediaAdvancementResource; | ||||||
|  | import org.atriasoft.karideo.api.UserResource; | ||||||
|  | import org.atriasoft.karideo.model.Media; | ||||||
|  | import org.atriasoft.karideo.model.Season; | ||||||
|  | import org.atriasoft.karideo.model.Series; | ||||||
|  | import org.atriasoft.karideo.model.Type; | ||||||
|  | import org.atriasoft.karideo.model.UserMediaAdvancement; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.InternalServerErrorException; | ||||||
|  |  | ||||||
|  | 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(Data.class, Media.class, Type.class, Series.class, Season.class, User.class, UserMediaAdvancement.class); | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public String getName() { | ||||||
|  | 		return "Initialization"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void removeDB() throws DataAccessException, InternalServerErrorException, IOException { | ||||||
|  | 		final DbConfig config = new DbConfig(); | ||||||
|  | 		LOGGER.info("Remove DB '{}'", config.getDbName()); | ||||||
|  | 		try (DBAccess dba = DBAccess.createInterface(config)) { | ||||||
|  | 			dba.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** Restore backup file (./init/backup.tar.gz). */ | ||||||
|  | 	public static void initializeWithBackup() throws IOException, DataAccessException, FailException { | ||||||
|  | 		final Path path = Paths.get("./init/backup.tar.gz"); | ||||||
|  | 		if (!Files.exists(path)) { | ||||||
|  | 			throw new FailException("file: ./init/backup.tar.gz does not exist"); | ||||||
|  | 		} | ||||||
|  | 		removeDB(); | ||||||
|  | 		final BackupEngine engine = new BackupEngine(Paths.get("."), ConfigBaseVariable.bdDatabase, EngineBackupType.JSON_EXTENDED); | ||||||
|  | 		if (!engine.restoreFile(path, null)) { | ||||||
|  | 			throw new FailException("Can not retrieve db from backup"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void generateObjects() throws Exception { | ||||||
|  | 		LOGGER.info("Generate APIs"); | ||||||
|  | 		final List<Class<?>> listOfResources = List.of(Front.class, HealthCheck.class, SeasonResource.class, SeriesResource.class, TypeResource.class, UserMediaAdvancementResource.class, | ||||||
|  | 				UserResource.class, MediaResource.class, DataResource.class); | ||||||
|  | 		final AnalyzeApi api = new AnalyzeApi(); | ||||||
|  | 		api.addAllApi(listOfResources); | ||||||
|  | 		api.addModel(JwtToken.class); | ||||||
|  | 		api.addModel(PartRight.class); | ||||||
|  | 		TsGenerateApi.generateApi(api, Paths.get("../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<Type> data = List.of(// | ||||||
|  | 					new Type("Documentary", "Documentary (animals, space, earth...)"), // | ||||||
|  | 					new Type("Movie", "Movie with real humans (film)"), // | ||||||
|  | 					new Type("Animation", "Animation movies (film)"), // | ||||||
|  | 					new Type("Short movie", "Small movies (less 2 minutes)"), // | ||||||
|  | 					new Type("TV show", "TV show for old peoples"), // | ||||||
|  | 					new Type("Animation TV show", "TV show for young peoples"), // | ||||||
|  | 					new Type("Theater", "Theater play"), // | ||||||
|  | 					new Type("One man show", "Recorded stand up"), // | ||||||
|  | 					new Type("Concert", "Recorded concert"), // | ||||||
|  | 					new Type("Opera", "Recorded opera") // | ||||||
|  | 			); | ||||||
|  | 			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(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,41 @@ | |||||||
|  | package org.atriasoft.karideo.migration; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.dataAccess.DBAccess; | ||||||
|  | import org.atriasoft.archidata.migration.MigrationSqlStep; | ||||||
|  | import org.atriasoft.karideo.migration.model.TypeOld; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class Migration20250928 extends MigrationSqlStep { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(Migration20250928.class); | ||||||
|  |  | ||||||
|  | 	public static final int KARSO_INITIALISATION_ID = 1; | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public String getName() { | ||||||
|  | 		return "migration-2025-10-12: Fix UserId in advencement"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static ObjectId getElementType(final List<TypeOld> 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) -> { | ||||||
|  |  | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										85
									
								
								back/src/org/atriasoft/karideo/migration/model/MediaOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								back/src/org/atriasoft/karideo/migration/model/MediaOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | package org.atriasoft.karideo.migration.model; | ||||||
|  |  | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataJson; | ||||||
|  | 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.GenericDataSoftDelete; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.hibernate.validator.constraints.UniqueElements; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.persistence.FetchType; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.PositiveOrZero; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Entity | ||||||
|  | @Table(name = "media") | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class MediaOld extends GenericDataSoftDelete { | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	@Column(nullable = false, length = 0) | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	public String name; | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Schema(description = "Foreign Key Id of the data") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class) | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@CheckForeignKey(target = Data.class) | ||||||
|  | 	public ObjectId dataId; | ||||||
|  | 	@Schema(description = "Type of the media") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = TypeOld.class) | ||||||
|  | 	@CheckForeignKey(target = TypeOld.class) | ||||||
|  | 	public Long typeId; | ||||||
|  | 	@Schema(description = "Series reference of the media") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = SeriesOld.class) | ||||||
|  | 	@CheckForeignKey(target = SeriesOld.class) | ||||||
|  | 	public Long seriesId; | ||||||
|  | 	@Schema(description = "Season reference of the media") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = SeasonOld.class) | ||||||
|  | 	@CheckForeignKey(target = SeasonOld.class) | ||||||
|  | 	public Long seasonId; | ||||||
|  | 	@Schema(description = "Episode Id") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer episode; | ||||||
|  | 	@Schema(description = "Creation years of the media") | ||||||
|  | 	public Date datePublication; | ||||||
|  | 	@Schema(description = "Limitation Age of the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer ageLimit; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson() | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public String toString() { | ||||||
|  | 		return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId | ||||||
|  | 				+ ", episode=" + this.episode + ", date=" + this.datePublication + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(nullable = true) | ||||||
|  | 	private final ObjectId oid = new ObjectId(); | ||||||
|  |  | ||||||
|  | 	public ObjectId getOid() { | ||||||
|  | 		return this.oid; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,57 @@ | |||||||
|  | package org.atriasoft.karideo.migration.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.atriasoft.archidata.annotation.DataJson; | ||||||
|  | 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.GenericDataSoftDelete; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.hibernate.validator.constraints.UniqueElements; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.FetchType; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Table(name = "season") | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class SeasonOld extends GenericDataSoftDelete { | ||||||
|  | 	@Column(nullable = false, length = 0) | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "series parent ID") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = SeriesOld.class) | ||||||
|  | 	@CheckForeignKey(target = SeriesOld.class) | ||||||
|  | 	public Long parentId; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson() | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	@Column(nullable = true) | ||||||
|  | 	private final ObjectId oid = new ObjectId(); | ||||||
|  |  | ||||||
|  | 	public ObjectId getOid() { | ||||||
|  | 		return this.oid; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,56 @@ | |||||||
|  | package org.atriasoft.karideo.migration.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.atriasoft.archidata.annotation.DataJson; | ||||||
|  | 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.GenericDataSoftDelete; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.hibernate.validator.constraints.UniqueElements; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.FetchType; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Table(name = "series") | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class SeriesOld extends GenericDataSoftDelete { | ||||||
|  | 	@Column(nullable = false, length = 0) | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "series parent ID") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = TypeOld.class) | ||||||
|  | 	@CheckForeignKey(target = TypeOld.class) | ||||||
|  | 	public Long parentId; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson() | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  | 	@Column(nullable = true) | ||||||
|  | 	private final ObjectId oid = new ObjectId(); | ||||||
|  |  | ||||||
|  | 	public ObjectId getOid() { | ||||||
|  | 		return this.oid; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								back/src/org/atriasoft/karideo/migration/model/TypeOld.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								back/src/org/atriasoft/karideo/migration/model/TypeOld.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | package org.atriasoft.karideo.migration.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.atriasoft.archidata.annotation.DataJson; | ||||||
|  | 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.GenericDataSoftDelete; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.hibernate.validator.constraints.UniqueElements; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Table(name = "type") | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class TypeOld extends GenericDataSoftDelete { | ||||||
|  | 	@Column(nullable = false, length = 0) | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@DataJson() | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	public TypeOld() {} | ||||||
|  |  | ||||||
|  | 	public TypeOld(final String name, final String description) { | ||||||
|  | 		this.name = name; | ||||||
|  | 		this.description = description; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Column(nullable = true) | ||||||
|  | 	private final ObjectId oid = new ObjectId(); | ||||||
|  |  | ||||||
|  | 	public ObjectId getOid() { | ||||||
|  | 		return this.oid; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,57 @@ | |||||||
|  | package org.atriasoft.karideo.migration.model; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.atriasoft.archidata.annotation.DataNotRead; | ||||||
|  | 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.model.GenericDataSoftDelete; | ||||||
|  | import org.atriasoft.karideo.model.UserKarideo; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.FetchType; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.PositiveOrZero; | ||||||
|  |  | ||||||
|  | @Table(name = "userMediaAdvancement") | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class UserMediaAdvancementOld extends GenericDataSoftDelete { | ||||||
|  | 	@DataNotRead | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "Foreign Key Id of the user") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class) | ||||||
|  | 	@Nullable | ||||||
|  | 	@ApiAccessLimitation(updatable = false, creatable = false) | ||||||
|  | 	public Long userId; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "Id of the media") | ||||||
|  | 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = MediaOld.class) | ||||||
|  | 	@CheckForeignKey(target = MediaOld.class) | ||||||
|  | 	public Long mediaId; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "Percent of advancement in the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Float percent; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "Number of second of advancement in the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer time; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "Number of time this media has been read") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer count; | ||||||
|  | 	@Column(nullable = true) | ||||||
|  | 	private final ObjectId oid = new ObjectId(); | ||||||
|  |  | ||||||
|  | 	public ObjectId getOid() { | ||||||
|  | 		return this.oid; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								back/src/org/atriasoft/karideo/model/Media.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								back/src/org/atriasoft/karideo/model/Media.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | package org.atriasoft.karideo.model; | ||||||
|  |  | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | 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 io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.PositiveOrZero; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Entity() | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class Media extends OIDGenericDataSoftDelete { | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	@NotNull | ||||||
|  | 	public String name; | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Schema(description = "Foreign Key Id of the data") | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@CheckForeignKey(target = Data.class) | ||||||
|  | 	public ObjectId dataId; | ||||||
|  | 	@Schema(description = "Type of the media") | ||||||
|  | 	@CheckForeignKey(target = Type.class) | ||||||
|  | 	public ObjectId typeId; | ||||||
|  | 	@Schema(description = "Series reference of the media") | ||||||
|  | 	@CheckForeignKey(target = Series.class) | ||||||
|  | 	public ObjectId seriesId; | ||||||
|  | 	@Schema(description = "Season reference of the media") | ||||||
|  | 	@CheckForeignKey(target = Season.class) | ||||||
|  | 	public ObjectId seasonId; | ||||||
|  | 	@Schema(description = "Episode Id") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer episode; | ||||||
|  | 	@Schema(description = "Creation years of the media") | ||||||
|  | 	public Date datePublication; | ||||||
|  | 	@Schema(description = "Limitation Age of the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer ageLimit; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public String toString() { | ||||||
|  | 		return "Media [name=" + this.name + ", description=" + this.description + ", dataId=" + this.dataId + ", typeId=" + this.typeId + ", seriesId=" + this.seriesId + ", seasonId=" + this.seasonId | ||||||
|  | 				+ ", episode=" + this.episode + ", date=" + this.datePublication + ", ageLimit=" + this.ageLimit + ", covers=" + this.covers + "]"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								back/src/org/atriasoft/karideo/model/Season.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								back/src/org/atriasoft/karideo/model/Season.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | package org.atriasoft.karideo.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | 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 io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Entity() | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class Season extends OIDGenericDataSoftDelete { | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	public String name; | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Schema(description = "series parent ID") | ||||||
|  | 	// @ManyToOneDoc(targetEntity = Series.class, remoteField = "") | ||||||
|  | 	@CheckForeignKey(target = Series.class) | ||||||
|  | 	public ObjectId seriesId; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								back/src/org/atriasoft/karideo/model/Series.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								back/src/org/atriasoft/karideo/model/Series.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | package org.atriasoft.karideo.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | 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 io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Entity() | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class Series extends OIDGenericDataSoftDelete { | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@Schema(description = "series parent ID") | ||||||
|  | 	@CheckForeignKey(target = Type.class) | ||||||
|  | 	public ObjectId typeId; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								back/src/org/atriasoft/karideo/model/Type.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								back/src/org/atriasoft/karideo/model/Type.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | package org.atriasoft.karideo.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | 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 io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.annotation.Nullable; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | @Entity() | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class Type extends OIDGenericDataSoftDelete { | ||||||
|  | 	@NotNull | ||||||
|  | 	@Size(min = 0, max = 256) | ||||||
|  | 	@Schema(description = "Name of the media (this represent the title)") | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	@Schema(description = "Description of the media") | ||||||
|  | 	@Size(min = 0, max = 8192) | ||||||
|  | 	public String description; | ||||||
|  | 	@Schema(description = "List of Id of the specific covers") | ||||||
|  | 	@Nullable | ||||||
|  | 	@CollectionNotEmpty | ||||||
|  | 	@UniqueElements | ||||||
|  | 	public List<@CheckForeignKey(target = Data.class) @NotNull ObjectId> covers = null; | ||||||
|  |  | ||||||
|  | 	public Type() {} | ||||||
|  |  | ||||||
|  | 	public Type(final String name, final String description) { | ||||||
|  | 		this.name = name; | ||||||
|  | 		this.description = description; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| package org.kar.karideo.model; | package org.atriasoft.karideo.model; | ||||||
| 
 | 
 | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
| import org.kar.archidata.model.User; | import org.atriasoft.archidata.model.User; | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
| 
 | 
 | ||||||
| @@ -0,0 +1,43 @@ | |||||||
|  | package org.atriasoft.karideo.model; | ||||||
|  |  | ||||||
|  | import org.atriasoft.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.atriasoft.archidata.annotation.DataNotRead; | ||||||
|  | import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode; | ||||||
|  | import org.atriasoft.archidata.annotation.checker.CheckForeignKey; | ||||||
|  | import org.atriasoft.archidata.model.OIDGenericDataSoftDelete; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.persistence.Entity; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.PositiveOrZero; | ||||||
|  |  | ||||||
|  | @Entity() | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | @ApiGenerationMode(create = true, update = true) | ||||||
|  | public class UserMediaAdvancement extends OIDGenericDataSoftDelete { | ||||||
|  | 	@DataNotRead | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Foreign Key Id of the user") | ||||||
|  | 	@CheckForeignKey(target = UserKarideo.class) | ||||||
|  | 	public ObjectId userId; | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Id of the media") | ||||||
|  | 	@CheckForeignKey(target = Media.class) | ||||||
|  | 	public ObjectId mediaId; | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Percent of advancement in the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Float percent; | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Number of second of advancement in the media") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer time; | ||||||
|  | 	@NotNull | ||||||
|  | 	@Schema(description = "Number of time this media has been read") | ||||||
|  | 	@PositiveOrZero | ||||||
|  | 	public Integer count; | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								back/src/org/atriasoft/karideo/util/ConfigVariable.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								back/src/org/atriasoft/karideo/util/ConfigVariable.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | package org.atriasoft.karideo.util; | ||||||
|  |  | ||||||
|  | public class ConfigVariable { | ||||||
|  | 	public static final String BASE_NAME = "ORG_KARIDEO_"; | ||||||
|  |  | ||||||
|  | 	public static String getFrontFolder() { | ||||||
|  | 		final String out = System.getenv(BASE_NAME + "FRONT_FOLDER"); | ||||||
|  | 		if (out == null) { | ||||||
|  | 			return "./front"; | ||||||
|  | 		} | ||||||
|  | 		return out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String getBackupFolder() { | ||||||
|  | 		final String out = System.getenv(BASE_NAME + "BACKUP_FOLDER"); | ||||||
|  | 		if (out == null) { | ||||||
|  | 			return "./backup"; | ||||||
|  | 		} | ||||||
|  | 		return out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static boolean isInitWithBackup() { | ||||||
|  | 		final String out = System.getenv(BASE_NAME + "INIT_WITH_BACKUP"); | ||||||
|  | 		if (out == null) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		return "true".equals(out); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,118 +0,0 @@ | |||||||
| package org.kar.karideo.api; |  | ||||||
|  |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.QueryAnd; |  | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; |  | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; |  | ||||||
| import org.kar.archidata.dataAccess.options.Condition; |  | ||||||
| import org.kar.archidata.tools.DataTools; |  | ||||||
| import org.kar.karideo.model.Season; |  | ||||||
| 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; |  | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/season") |  | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) |  | ||||||
| public class SeasonResource { |  | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(SeasonResource.class); |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public static Season getWithId(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Season.class, id); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public List<Season> get() throws Exception { |  | ||||||
| 		return DataAccess.gets(Season.class); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Season get(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Season.class, id); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	/* ============================================================================= |  | ||||||
| 	 * ADMIN SECTION: |  | ||||||
| 	 * ============================================================================= */ |  | ||||||
| 	 |  | ||||||
| 	@POST |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Season put(final String jsonRequest) throws Exception { |  | ||||||
| 		return DataAccess.insertWithJson(Season.class, jsonRequest); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@PATCH |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Season put(@PathParam("id") final Long id, final String jsonRequest) throws Exception { |  | ||||||
| 		DataAccess.updateWithJson(Season.class, id, jsonRequest); |  | ||||||
| 		return DataAccess.get(Season.class, id); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@DELETE |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response delete(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		DataAccess.delete(Season.class, id); |  | ||||||
| 		return Response.ok().build(); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@POST |  | ||||||
| 	@Path("{id}/add_cover") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) |  | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, |  | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		return DataTools.uploadCover(Season.class, id, fileName, fileInputStream, fileMetaData); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}/rm_cover/{coverId}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception { |  | ||||||
| 		AddOnManyToMany.removeLink(Season.class, id, "cover", coverId); |  | ||||||
| 		return Response.ok(DataAccess.get(Season.class, id)).build(); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public static Season getOrCreate(final String name, final Long seriesId) { |  | ||||||
| 		try { |  | ||||||
| 			Season out = DataAccess.getWhere(Season.class, new Condition(new QueryAnd(new QueryCondition("name", "=", name), new QueryCondition("parentId", "=", seriesId)))); |  | ||||||
| 			if (out == null) { |  | ||||||
| 				out = new Season(); |  | ||||||
| 				out.name = name; |  | ||||||
| 				out.parentId = seriesId; |  | ||||||
| 				out = DataAccess.insert(out); |  | ||||||
| 			} |  | ||||||
| 			return out; |  | ||||||
| 		} catch (final Exception e) { |  | ||||||
| 			// TODO Auto-generated catch block |  | ||||||
| 			e.printStackTrace(); |  | ||||||
| 		} |  | ||||||
| 		return null; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| } |  | ||||||
| @@ -1,118 +0,0 @@ | |||||||
| package org.kar.karideo.api; |  | ||||||
|  |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.QueryAnd; |  | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; |  | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; |  | ||||||
| import org.kar.archidata.dataAccess.options.Condition; |  | ||||||
| import org.kar.archidata.tools.DataTools; |  | ||||||
| import org.kar.karideo.model.Series; |  | ||||||
| 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; |  | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/series") |  | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) |  | ||||||
| public class SeriesResource { |  | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(SeriesResource.class); |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public static Series getWithId(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Series.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public List<Series> get() throws Exception { |  | ||||||
| 		return DataAccess.gets(Series.class); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Series get(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Series.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* ============================================================================= |  | ||||||
| 	 * ADMIN SECTION: |  | ||||||
| 	 * ============================================================================= */ |  | ||||||
|  |  | ||||||
| 	@POST |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Series put(final String jsonRequest) throws Exception { |  | ||||||
| 		return DataAccess.insertWithJson(Series.class, jsonRequest); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@PATCH |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Series put(@PathParam("id") final Long id, final String jsonRequest) throws Exception { |  | ||||||
| 		DataAccess.updateWithJson(Series.class, id, jsonRequest); |  | ||||||
| 		return DataAccess.get(Series.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@DELETE |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response delete(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		DataAccess.delete(Series.class, id); |  | ||||||
| 		return Response.ok().build(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@POST |  | ||||||
| 	@Path("{id}/add_cover") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) |  | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, |  | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		return DataTools.uploadCover(Series.class, id, fileName, fileInputStream, fileMetaData); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}/rm_cover/{coverId}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception { |  | ||||||
| 		AddOnManyToMany.removeLink(Series.class, id, "cover", coverId); |  | ||||||
| 		return Response.ok(DataAccess.get(Series.class, id)).build(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public static Series getOrCreate(final String name, final Long typeId) { |  | ||||||
| 		try { |  | ||||||
| 			Series out = DataAccess.getWhere(Series.class, new Condition(new QueryAnd(new QueryCondition("name", "=", name), new QueryCondition("parentId", "=", typeId)))); |  | ||||||
| 			if (out == null) { |  | ||||||
| 				out = new Series(); |  | ||||||
| 				out.name = name; |  | ||||||
| 				out.parentId = typeId; |  | ||||||
| 				out = DataAccess.insert(out); |  | ||||||
| 			} |  | ||||||
| 			return out; |  | ||||||
| 		} catch (final Exception e) { |  | ||||||
| 			// TODO Auto-generated catch block |  | ||||||
| 			e.printStackTrace(); |  | ||||||
| 		} |  | ||||||
| 		return null; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,120 +0,0 @@ | |||||||
| package org.kar.karideo.api; |  | ||||||
|  |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; |  | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; |  | ||||||
| import org.kar.archidata.dataAccess.options.Condition; |  | ||||||
| import org.kar.archidata.tools.DataTools; |  | ||||||
| import org.kar.karideo.model.Type; |  | ||||||
| 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; |  | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/type") |  | ||||||
| @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) |  | ||||||
| public class TypeResource { |  | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(TypeResource.class); |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public static Type getWithId(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Type.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public List<Type> get() throws Exception { |  | ||||||
| 		return DataAccess.gets(Type.class); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Type get(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Type.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public static Type getId(final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Type.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* ============================================================================= |  | ||||||
| 	 * ADMIN SECTION: |  | ||||||
| 	 * ============================================================================= */ |  | ||||||
|  |  | ||||||
| 	@POST |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Type put(final String jsonRequest) throws Exception { |  | ||||||
| 		return DataAccess.insertWithJson(Type.class, jsonRequest); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@PATCH |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Type put(@PathParam("id") final Long id, final String jsonRequest) throws Exception { |  | ||||||
| 		DataAccess.updateWithJson(Type.class, id, jsonRequest); |  | ||||||
| 		return DataAccess.get(Type.class, id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@DELETE |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response delete(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		DataAccess.delete(Type.class, id); |  | ||||||
| 		return Response.ok().build(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@POST |  | ||||||
| 	@Path("{id}/add_cover") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) |  | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, |  | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		return DataTools.uploadCover(Type.class, id, fileName, fileInputStream, fileMetaData); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}/rm_cover/{coverId}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception { |  | ||||||
| 		AddOnManyToMany.removeLink(Type.class, id, "cover", coverId); |  | ||||||
| 		return Response.ok(DataAccess.get(Type.class, id)).build(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public static Type getOrCreate(final String name) { |  | ||||||
| 		try { |  | ||||||
| 			Type out = DataAccess.getWhere(Type.class, new Condition(new QueryCondition("name", "=", name))); |  | ||||||
| 			if (out == null) { |  | ||||||
| 				out = new Type(); |  | ||||||
| 				out.name = name; |  | ||||||
| 				out = DataAccess.insert(out); |  | ||||||
| 			} |  | ||||||
| 			return out; |  | ||||||
| 		} catch (final Exception e) { |  | ||||||
| 			// TODO Auto-generated catch block |  | ||||||
| 			e.printStackTrace(); |  | ||||||
| 		} |  | ||||||
| 		return null; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,109 +0,0 @@ | |||||||
| package org.kar.karideo.api; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.QueryAnd; |  | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; |  | ||||||
| import org.kar.archidata.dataAccess.options.Condition; |  | ||||||
| import org.kar.archidata.filter.GenericContext; |  | ||||||
| import org.kar.karideo.model.UserMediaAdvancement; |  | ||||||
| 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.Path; |  | ||||||
| import jakarta.ws.rs.PathParam; |  | ||||||
| import jakarta.ws.rs.Produces; |  | ||||||
| import jakarta.ws.rs.core.Context; |  | ||||||
| import jakarta.ws.rs.core.MediaType; |  | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
| import jakarta.ws.rs.core.SecurityContext; |  | ||||||
|  |  | ||||||
| @Path("/advancement") |  | ||||||
| @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) |  | ||||||
| public class UserMediaAdvancementResource { |  | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(UserMediaAdvancementResource.class); |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public UserMediaAdvancement getWithId(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception { |  | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); |  | ||||||
| 		return DataAccess.getWhere(UserMediaAdvancement.class, new Condition(new QueryAnd(new QueryCondition("mediaId", "=", id), new QueryCondition("userId", "=", gc.userByToken.id)))); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@GET |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public List<UserMediaAdvancement> gets(@Context final SecurityContext sc) throws Exception { |  | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); |  | ||||||
| 		return DataAccess.getsWhere(UserMediaAdvancement.class, new Condition(new QueryCondition("userId", "=", gc.userByToken.id))); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* ============================================================================= |  | ||||||
| 	 * Modification SECTION: |  | ||||||
| 	 * ============================================================================= */ |  | ||||||
|  |  | ||||||
| 	public record MediaInformations( |  | ||||||
| 			int time, |  | ||||||
| 			float percent, |  | ||||||
| 			int count) {} |  | ||||||
|  |  | ||||||
| 	//@POST |  | ||||||
| 	//@Path("{id}") |  | ||||||
| 	//@RolesAllowed("USER") |  | ||||||
| 	//@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public UserMediaAdvancement post(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformations data) throws Exception { |  | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); |  | ||||||
| 		final UserMediaAdvancement elem = new UserMediaAdvancement(); |  | ||||||
| 		elem.userId = gc.userByToken.id; |  | ||||||
| 		elem.mediaId = id; |  | ||||||
| 		elem.time = data.time; |  | ||||||
| 		elem.percent = data.percent; |  | ||||||
| 		elem.count = data.count; |  | ||||||
| 		return DataAccess.insert(elem); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public record MediaInformationsDelta( |  | ||||||
| 			int time, |  | ||||||
| 			float percent, |  | ||||||
| 			boolean addCount) {} |  | ||||||
|  |  | ||||||
| 	@PATCH |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public UserMediaAdvancement put(@Context final SecurityContext sc, @PathParam("id") final Long id, final MediaInformationsDelta data) throws Exception { |  | ||||||
| 		final UserMediaAdvancement elem = getWithId(sc, id); |  | ||||||
| 		if (elem == null) { |  | ||||||
| 			// insert element |  | ||||||
| 			if (data.addCount) { |  | ||||||
| 				return post(sc, id, new MediaInformations(data.time(), data.percent(), 1)); |  | ||||||
| 			} else { |  | ||||||
| 				return post(sc, id, new MediaInformations(data.time(), data.percent(), 0)); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		elem.time = data.time; |  | ||||||
| 		elem.percent = data.percent; |  | ||||||
| 		if (data.addCount) { |  | ||||||
| 			elem.count++; |  | ||||||
| 		} |  | ||||||
| 		LOGGER.info("{},{},{}", elem.time, elem.percent, elem.count); |  | ||||||
| 		final int nbAfected = DataAccess.update(elem, elem.id, List.of("time", "percent", "count")); |  | ||||||
| 		return DataAccess.get(UserMediaAdvancement.class, elem.id); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@DELETE |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public Response delete(@Context final SecurityContext sc, @PathParam("id") final Long id) throws Exception { |  | ||||||
| 		final UserMediaAdvancement elem = getWithId(sc, id); |  | ||||||
| 		DataAccess.delete(UserMediaAdvancement.class, elem.id); |  | ||||||
| 		return Response.ok().build(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,223 +0,0 @@ | |||||||
| package org.kar.karideo.api; |  | ||||||
|  |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.sql.SQLException; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; |  | ||||||
| import org.kar.archidata.api.DataResource; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; |  | ||||||
| import org.kar.archidata.exception.FailException; |  | ||||||
| import org.kar.archidata.exception.InputException; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.tools.DataTools; |  | ||||||
| import org.kar.karideo.model.Media; |  | ||||||
| import org.kar.karideo.model.Season; |  | ||||||
| import org.kar.karideo.model.Series; |  | ||||||
| import org.kar.karideo.model.Type; |  | ||||||
| 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; |  | ||||||
| import jakarta.ws.rs.core.Response; |  | ||||||
|  |  | ||||||
| @Path("/video") |  | ||||||
| @Produces({ MediaType.APPLICATION_JSON }) |  | ||||||
| public class VideoResource { |  | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(VideoResource.class); |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public List<Media> get() throws Exception { |  | ||||||
| 		return DataAccess.gets(Media.class); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("USER") |  | ||||||
| 	public Media get(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		return DataAccess.get(Media.class, id); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@PATCH |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes(MediaType.APPLICATION_JSON) |  | ||||||
| 	public Media put(@PathParam("id") final Long id, final String jsonRequest) throws Exception { |  | ||||||
| 		System.out.println("update video " + id + " ==> '" + jsonRequest + "'"); |  | ||||||
| 		DataAccess.updateWithJson(Media.class, id, jsonRequest); |  | ||||||
| 		return DataAccess.get(Media.class, id); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	private String multipartCorrection(final String data) { |  | ||||||
| 		if (data == null) { |  | ||||||
| 			return null; |  | ||||||
| 		} |  | ||||||
| 		if (data.isEmpty()) { |  | ||||||
| 			return null; |  | ||||||
| 		} |  | ||||||
| 		if (data.contentEquals("null")) { |  | ||||||
| 			return null; |  | ||||||
| 		} |  | ||||||
| 		return data; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@POST |  | ||||||
| 	@Path("/upload/") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) |  | ||||||
| 	public Response uploadFile(@FormDataParam("fileName") String fileName, @FormDataParam("universe") String universe, @FormDataParam("series") String series, |  | ||||||
| 			//@FormDataParam("seriesId") String seriesId, Not used ... |  | ||||||
| 			@FormDataParam("season") String season, @FormDataParam("episode") String episode, @FormDataParam("title") String title, @FormDataParam("typeId") String typeId, |  | ||||||
| 			@FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws FailException { |  | ||||||
| 		try { |  | ||||||
| 			// correct input string stream : |  | ||||||
| 			fileName = multipartCorrection(fileName); |  | ||||||
| 			universe = multipartCorrection(universe); |  | ||||||
| 			series = multipartCorrection(series); |  | ||||||
| 			season = multipartCorrection(season); |  | ||||||
| 			episode = multipartCorrection(episode); |  | ||||||
| 			title = multipartCorrection(title); |  | ||||||
| 			typeId = multipartCorrection(typeId); |  | ||||||
| 			 |  | ||||||
| 			//public NodeSmall uploadFile(final FormDataMultiPart form) { |  | ||||||
| 			System.out.println("Upload media file: " + fileMetaData); |  | ||||||
| 			System.out.println("    - fileName: " + fileName); |  | ||||||
| 			System.out.println("    - universe: " + universe); |  | ||||||
| 			System.out.println("    - series: " + series); |  | ||||||
| 			System.out.println("    - season: " + season); |  | ||||||
| 			System.out.println("    - episode: " + episode); |  | ||||||
| 			System.out.println("    - title: " + title); |  | ||||||
| 			System.out.println("    - type: " + typeId); |  | ||||||
| 			System.out.println("    - fileInputStream: " + fileInputStream); |  | ||||||
| 			System.out.println("    - fileMetaData: " + fileMetaData); |  | ||||||
| 			System.out.flush(); |  | ||||||
| 			if (typeId == null) { |  | ||||||
| 				throw new InputException("typeId", "TypiId is not specified"); |  | ||||||
| 			} |  | ||||||
| 			 |  | ||||||
| 			final long tmpUID = DataResource.getTmpDataId(); |  | ||||||
| 			final String sha512 = DataResource.saveTemporaryFile(fileInputStream, tmpUID); |  | ||||||
| 			Data data = DataResource.getWithSha512(sha512); |  | ||||||
| 			if (data == null) { |  | ||||||
| 				System.out.println("Need to add the data in the BDD ... "); |  | ||||||
| 				System.out.flush(); |  | ||||||
| 				try { |  | ||||||
| 					data = DataResource.createNewData(tmpUID, fileName, sha512); |  | ||||||
| 				} catch (final IOException ex) { |  | ||||||
| 					DataResource.removeTemporaryFile(tmpUID); |  | ||||||
| 					ex.printStackTrace(); |  | ||||||
| 					throw new FailException("can not create input media (the data model has an internal error"); |  | ||||||
| 				} |  | ||||||
| 			} else if (data.deleted) { |  | ||||||
| 				System.out.println("Data already exist but deleted"); |  | ||||||
| 				System.out.flush(); |  | ||||||
| 				DataResource.undelete(data.id); |  | ||||||
| 				data.deleted = false; |  | ||||||
| 			} else { |  | ||||||
| 				System.out.println("Data already exist ... all good"); |  | ||||||
| 				System.out.flush(); |  | ||||||
| 			} |  | ||||||
| 			// Fist step: retive all the Id of each parents:... |  | ||||||
| 			System.out.println("Find typeNode"); |  | ||||||
| 			// check if id of type exist: |  | ||||||
| 			final Type typeNode = TypeResource.getId(Long.parseLong(typeId)); |  | ||||||
| 			if (typeNode == null) { |  | ||||||
| 				DataResource.removeTemporaryFile(tmpUID); |  | ||||||
| 				throw new InputException("typeId", "TypeId does not exist ..."); |  | ||||||
| 			} |  | ||||||
| 			System.out.println("    ==> " + typeNode); |  | ||||||
| 			System.out.println("Find seriesNode"); |  | ||||||
| 			// get uid of group: |  | ||||||
| 			Series seriesNode = null; |  | ||||||
| 			if (series != null) { |  | ||||||
| 				seriesNode = SeriesResource.getOrCreate(series, typeNode.id); |  | ||||||
| 			} |  | ||||||
| 			 |  | ||||||
| 			System.out.println("    ==> " + seriesNode); |  | ||||||
| 			System.out.println("Find seasonNode"); |  | ||||||
| 			// get uid of season: |  | ||||||
| 			Season seasonNode = null; |  | ||||||
| 			if (seriesNode == null && season != null) { |  | ||||||
| 				DataResource.removeTemporaryFile(tmpUID); |  | ||||||
| 				throw new InputException("season", "Season is set but no seraies is set !!"); |  | ||||||
| 			} |  | ||||||
| 			if (season != null) { |  | ||||||
| 				seasonNode = SeasonResource.getOrCreate(season, seriesNode.id); |  | ||||||
| 			} |  | ||||||
| 			 |  | ||||||
| 			System.out.println("    ==> " + seasonNode); |  | ||||||
| 			System.out.println("add media"); |  | ||||||
| 			 |  | ||||||
| 			final long uniqueSQLID = -1; |  | ||||||
| 			try { |  | ||||||
| 				final Media media = new Media(); |  | ||||||
| 				media.name = title; |  | ||||||
| 				media.dataId = data.id; |  | ||||||
| 				media.typeId = typeNode.id; |  | ||||||
| 				media.seriesId = null; |  | ||||||
| 				if (seriesNode != null) { |  | ||||||
| 					media.seriesId = seriesNode.id; |  | ||||||
| 				} |  | ||||||
| 				media.seasonId = null; |  | ||||||
| 				if (seasonNode != null) { |  | ||||||
| 					media.seasonId = seasonNode.id; |  | ||||||
| 				} |  | ||||||
| 				media.episode = null; |  | ||||||
| 				if (episode != null && !episode.contentEquals("")) { |  | ||||||
| 					media.episode = Integer.parseInt(episode); |  | ||||||
| 				} |  | ||||||
| 				final Media out = DataAccess.insert(media); |  | ||||||
| 				DataResource.removeTemporaryFile(tmpUID); |  | ||||||
| 				System.out.println("uploaded .... compleate: " + uniqueSQLID); |  | ||||||
| 				final Media creation = get(uniqueSQLID); |  | ||||||
| 				return Response.ok(creation).build(); |  | ||||||
| 			} catch (final SQLException ex) { |  | ||||||
| 				ex.printStackTrace(); |  | ||||||
| 				System.out.println("Catch error:" + ex.getMessage()); |  | ||||||
| 				throw new FailException("Catch SQLerror ==> check server logs"); |  | ||||||
| 			} |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			System.out.println("Catch an unexpected error ... " + ex.getMessage()); |  | ||||||
| 			ex.printStackTrace(); |  | ||||||
| 			throw new FailException("Catch Exception ==> check server logs"); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@POST |  | ||||||
| 	@Path("{id}/add_cover") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) |  | ||||||
| 	public Response uploadCover(@PathParam("id") final Long id, @FormDataParam("fileName") final String fileName, @FormDataParam("file") final InputStream fileInputStream, |  | ||||||
| 			@FormDataParam("file") final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		return DataTools.uploadCover(Media.class, id, fileName, fileInputStream, fileMetaData); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@GET |  | ||||||
| 	@Path("{id}/rm_cover/{coverId}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response removeCover(@PathParam("id") final Long id, @PathParam("coverId") final Long coverId) throws Exception { |  | ||||||
| 		AddOnManyToMany.removeLink(Media.class, id, "cover", coverId); |  | ||||||
| 		return Response.ok(DataAccess.get(Media.class, id)).build(); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@DELETE |  | ||||||
| 	@Path("{id}") |  | ||||||
| 	@RolesAllowed("ADMIN") |  | ||||||
| 	public Response delete(@PathParam("id") final Long id) throws Exception { |  | ||||||
| 		DataAccess.delete(Media.class, id); |  | ||||||
| 		return Response.ok().build(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,60 +0,0 @@ | |||||||
| package org.kar.karideo.internal; |  | ||||||
|  |  | ||||||
| //import io.scenarium.logger.LogLevel; |  | ||||||
| //import io.scenarium.logger.Logger; |  | ||||||
|  |  | ||||||
| public class Log { |  | ||||||
| //	private static final String LIB_NAME = "logger"; |  | ||||||
| //	private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); |  | ||||||
| //	private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); |  | ||||||
| //	private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); |  | ||||||
| //	private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); |  | ||||||
| //	private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); |  | ||||||
| //	private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); |  | ||||||
| //	private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); |  | ||||||
| //	private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); |  | ||||||
| //	private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); |  | ||||||
| // |  | ||||||
| //	private Log() {} |  | ||||||
| // |  | ||||||
| //	public static void print(String data) { |  | ||||||
| //		if (PRINT_PRINT) |  | ||||||
| //			Logger.print(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void todo(String data) { |  | ||||||
| //		if (PRINT_TODO) |  | ||||||
| //			Logger.todo(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void critical(String data) { |  | ||||||
| //		if (PRINT_CRITICAL) |  | ||||||
| //			Logger.critical(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void error(String data) { |  | ||||||
| //		if (PRINT_ERROR) |  | ||||||
| //			Logger.error(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void warning(String data) { |  | ||||||
| //		if (PRINT_WARNING) |  | ||||||
| //			Logger.warning(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void info(String data) { |  | ||||||
| //		if (PRINT_INFO) |  | ||||||
| //			Logger.info(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void debug(String data) { |  | ||||||
| //		if (PRINT_DEBUG) |  | ||||||
| //			Logger.debug(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
| // |  | ||||||
| //	public static void verbose(String data) { |  | ||||||
| //		if (PRINT_VERBOSE) |  | ||||||
| //			Logger.verbose(LIB_NAME_DRAW, data); |  | ||||||
| //	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,69 +0,0 @@ | |||||||
| package org.kar.karideo.migration; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.User; |  | ||||||
| import org.kar.karideo.model.Media; |  | ||||||
| import org.kar.karideo.model.Season; |  | ||||||
| import org.kar.karideo.model.Series; |  | ||||||
| import org.kar.karideo.model.Type; |  | ||||||
| import org.kar.karideo.model.UserMediaAdvancement; |  | ||||||
|  |  | ||||||
| public class Initialization extends MigrationSqlStep { |  | ||||||
|  |  | ||||||
| 	public static final int KARSO_INITIALISATION_ID = 1; |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public String getName() { |  | ||||||
| 		return "Initialization"; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public Initialization() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		addClass(Data.class); |  | ||||||
| 		addClass(Media.class); |  | ||||||
| 		addClass(Type.class); |  | ||||||
| 		addClass(Series.class); |  | ||||||
| 		addClass(Season.class); |  | ||||||
| 		addClass(User.class); |  | ||||||
| 		addClass(UserMediaAdvancement.class); |  | ||||||
|  |  | ||||||
| 		addAction(""" |  | ||||||
| 				INSERT INTO `type` (`id`, `name`, `description`) VALUES |  | ||||||
| 				(1,  'Documentary',       'Documentary (animals, space, earth...)'), |  | ||||||
| 				(2,  'Movie',             'Movie with real humans (film)'), |  | ||||||
| 				(3,  'Animation',         'Animation movies (film)'), |  | ||||||
| 				(4,  'Short movie',       'Small movies (less 2 minutes)'), |  | ||||||
| 				(5,  'TV show',           'TV show for old peoples'), |  | ||||||
| 				(6,  'Animation TV show', 'TV show for young peoples'), |  | ||||||
| 				(7,  'Theater',           'Theater play'), |  | ||||||
| 				(8,  'One man show',      'Recorded stand up'), |  | ||||||
| 				(9,  'Concert',           'Recorded concert'), |  | ||||||
| 				(10, 'Opera',             'Recorded opera'); |  | ||||||
| 				"""); |  | ||||||
| 		// set start increment element to permit to add after default elements |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `media` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `type` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `series` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `season` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `userMediaAdvancement` AUTO_INCREMENT = 1000; |  | ||||||
| 				""", "mysql"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| package org.kar.karideo.migration; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; |  | ||||||
| import org.kar.karideo.model.UserMediaAdvancement; |  | ||||||
|  |  | ||||||
| public class Migration20230810 extends MigrationSqlStep { |  | ||||||
| 	 |  | ||||||
| 	public static final int KARSO_INITIALISATION_ID = 1; |  | ||||||
| 	 |  | ||||||
| 	@Override |  | ||||||
| 	public String getName() { |  | ||||||
| 		return "migration-2023-08-10"; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public Migration20230810() { |  | ||||||
| 		 |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		addClass(UserMediaAdvancement.class); |  | ||||||
| 		 |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `userMediaAdvancement` AUTO_INCREMENT = 1000; |  | ||||||
| 				"""); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| } |  | ||||||
| @@ -1,32 +0,0 @@ | |||||||
| package org.kar.karideo.migration; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; |  | ||||||
|  |  | ||||||
| public class Migration20231015 extends MigrationSqlStep { |  | ||||||
|  |  | ||||||
| 	public static final int KARSO_INITIALISATION_ID = 1; |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public String getName() { |  | ||||||
| 		return "migration-2023-10-15: refactor creation and update time"; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public Migration20231015() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		for (String elem : List.of("data", "media", "media_link_cover", "season", "season_link_cover", "series", "series_link_cover", "type", "type_link_cover", "user", "userMediaAdvancement")) { |  | ||||||
| 			addAction(""" |  | ||||||
| 					ALTER TABLE `""" + elem + """ |  | ||||||
| 					` |  | ||||||
| 						RENAME COLUMN `create_date` TO `createdAt`, |  | ||||||
| 						RENAME COLUMN `modify_date` TO `updatedAt`; |  | ||||||
| 					"""); |  | ||||||
| 		} |  | ||||||
| 		display(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,160 +0,0 @@ | |||||||
| package org.kar.karideo.migration; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.migration.MigrationSqlStep; |  | ||||||
|  |  | ||||||
| public class Migration20231126 extends MigrationSqlStep { |  | ||||||
|  |  | ||||||
| 	public static final int KARSO_INITIALISATION_ID = 1; |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public String getName() { |  | ||||||
| 		return "migration-2023-11-26: re-order the migration for the new API of archidata"; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public Migration20231126() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void generateStep() throws Exception { |  | ||||||
| 		 |  | ||||||
| 		// update migration update (last one) |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `KAR_migration` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				ADD `version` int NOT NULL DEFAULT '2' AFTER `deleted`, |  | ||||||
| 				CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'Name of the migration' AFTER `version`, |  | ||||||
| 				CHANGE `terminated` `terminated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'if the migration is well terminated or not' AFTER `name`, |  | ||||||
| 				CHANGE `stepId` `stepId` int NULL COMMENT 'index in the migration progression' AFTER `terminated`, |  | ||||||
| 				CHANGE `count` `count` int NULL COMMENT 'number of element in the migration' AFTER `stepId`, |  | ||||||
| 				CHANGE `log` `log` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Log generate by the migration' AFTER `count`; |  | ||||||
| 				"""); |  | ||||||
|  |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `data` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `sha512` `sha512` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Sha512 of the data' AFTER `deleted`, |  | ||||||
| 				CHANGE `mimeType` `mimeType` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Mime -type of the media' AFTER `sha512`, |  | ||||||
| 				CHANGE `size` `size` bigint NOT NULL COMMENT 'Size in Byte of the data' AFTER `mimeType`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `media` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `name` `name` text COLLATE 'utf8mb3_general_ci' NOT NULL COMMENT 'Name of the media (this represent the title)' AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Description of the media' AFTER `name`, |  | ||||||
| 				CHANGE `dataId` `dataId` bigint NOT NULL COMMENT 'Foreign Key Id of the data' AFTER `description`, |  | ||||||
| 				CHANGE `typeId` `typeId` bigint NULL COMMENT 'Type of the media' AFTER `dataId`, |  | ||||||
| 				CHANGE `seriesId` `seriesId` bigint NULL COMMENT 'Series reference of the media' AFTER `typeId`, |  | ||||||
| 				CHANGE `seasonId` `seasonId` bigint NULL COMMENT 'Saison reference of the media' AFTER `seriesId`, |  | ||||||
| 				CHANGE `episode` `episode` int NULL COMMENT 'Episide Id' AFTER `seasonId`, |  | ||||||
| 				CHANGE `date` `date` int NULL AFTER `episode`, |  | ||||||
| 				CHANGE `time` `time` int NULL COMMENT 'Creation years of the media' AFTER `date`, |  | ||||||
| 				CHANGE `ageLimit` `ageLimit` int NULL COMMENT 'Limitation Age of the media' AFTER `time`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `media_link_cover` |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `media_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `season` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `name` `name` text COLLATE 'utf8mb3_general_ci' NOT NULL COMMENT 'Name of the media (this represent the title)' AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Description of the media' AFTER `name`, |  | ||||||
| 				CHANGE `parentId` `parentId` bigint NOT NULL COMMENT 'series parent ID' AFTER `description`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `season_link_cover` |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `season_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `series` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `name` `name` text COLLATE 'utf8mb3_general_ci' NOT NULL COMMENT 'Name of the media (this represent the title)' AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Description of the media' AFTER `name`, |  | ||||||
| 				CHANGE `parentId` `parentId` bigint NOT NULL COMMENT 'series parent ID' AFTER `description`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `series_link_cover` |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `series_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `type` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `name` `name` text COLLATE 'utf8mb3_general_ci' NOT NULL COMMENT 'Name of the media (this represent the title)' AFTER `deleted`, |  | ||||||
| 				CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Description of the media' AFTER `name`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `type_link_cover` |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `type_id` `object1id` bigint NOT NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `user` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `login` `login` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`, |  | ||||||
| 				CHANGE `lastConnection` `lastConnection` timestamp(3) NULL AFTER `login`, |  | ||||||
| 				CHANGE `admin` `admin` tinyint(1) NOT NULL DEFAULT '0' AFTER `lastConnection`, |  | ||||||
| 				CHANGE `blocked` `blocked` tinyint(1) NOT NULL DEFAULT '0' AFTER `admin`, |  | ||||||
| 				CHANGE `removed` `removed` tinyint(1) NOT NULL DEFAULT '0' AFTER `blocked`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				ALTER TABLE `userMediaAdvancement` |  | ||||||
| 				CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST, |  | ||||||
| 				CHANGE `createdAt` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`, |  | ||||||
| 				CHANGE `updatedAt` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`, |  | ||||||
| 				CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`, |  | ||||||
| 				CHANGE `userId` `userId` bigint NOT NULL COMMENT 'Foreign Key Id of the user' AFTER `deleted`, |  | ||||||
| 				CHANGE `mediaId` `mediaId` bigint NOT NULL COMMENT 'Id of the media' AFTER `userId`, |  | ||||||
| 				CHANGE `percent` `percent` float NOT NULL COMMENT 'Percent of admencement in the media' AFTER `mediaId`, |  | ||||||
| 				CHANGE `time` `time` int NOT NULL COMMENT 'Number of second of admencement in the media' AFTER `percent`, |  | ||||||
| 				CHANGE `count` `count` int NOT NULL COMMENT 'Number of time this media has been read' AFTER `time`; |  | ||||||
| 				"""); |  | ||||||
| 		addAction(""" |  | ||||||
| 				CREATE TABLE `user_link_cover` ( |  | ||||||
| 					`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key of the base' , |  | ||||||
| 					`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' , |  | ||||||
| 					`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'When update the object' , |  | ||||||
| 					`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' , |  | ||||||
| 					`object1Id` bigint NOT NULL COMMENT 'Object reference 1' , |  | ||||||
| 					`object2Id` bigint NOT NULL COMMENT 'Object reference 2' , |  | ||||||
| 				PRIMARY KEY (`id`) |  | ||||||
| 				) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; |  | ||||||
| 				"""); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,53 +0,0 @@ | |||||||
| package org.kar.karideo.model; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.Entity; |  | ||||||
| import jakarta.persistence.FetchType; |  | ||||||
| import jakarta.persistence.ManyToMany; |  | ||||||
| import jakarta.persistence.ManyToOne; |  | ||||||
| import jakarta.persistence.Table; |  | ||||||
|  |  | ||||||
| @Entity |  | ||||||
| @Table(name = "media") |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| //@SQLDelete(sql = "UPDATE table_product SET deleted = true WHERE id=?") |  | ||||||
| //@Where(clause = "deleted=false") |  | ||||||
| public class Media extends GenericDataSoftDelete { |  | ||||||
| 	// Name of the media (this represent the title) |  | ||||||
| 	@Column(nullable = false, length = 0) |  | ||||||
| 	public String name; |  | ||||||
| 	// Description of the media |  | ||||||
| 	@Column(length = 0) |  | ||||||
| 	public String description; |  | ||||||
| 	// Foreign Key Id of the data |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class) |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	public Long dataId; |  | ||||||
| 	// Type of the media") |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class) |  | ||||||
| 	public Long typeId; |  | ||||||
| 	// Series reference of the media |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class) |  | ||||||
| 	public Long seriesId; |  | ||||||
| 	// Saison reference of the media |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Season.class) |  | ||||||
| 	public Long seasonId; |  | ||||||
| 	// Episide Id |  | ||||||
| 	public Integer episode; |  | ||||||
| 	// ") |  | ||||||
| 	public Integer date; |  | ||||||
| 	// Creation years of the media |  | ||||||
| 	public Integer time; |  | ||||||
| 	// Limitation Age of the media |  | ||||||
| 	public Integer ageLimit; |  | ||||||
| 	// List of Id of the specific covers |  | ||||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class) |  | ||||||
| 	public List<Long> covers = null; |  | ||||||
| } |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| package org.kar.karideo.model; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.FetchType; |  | ||||||
| import jakarta.persistence.ManyToMany; |  | ||||||
| import jakarta.persistence.ManyToOne; |  | ||||||
| import jakarta.persistence.Table; |  | ||||||
|  |  | ||||||
| @Table(name = "season") |  | ||||||
| @DataIfNotExists |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| public class Season extends GenericDataSoftDelete { |  | ||||||
| 	@Column(nullable = false, length = 0) |  | ||||||
| 	@Schema(description = "Name of the media (this represent the title)") |  | ||||||
| 	public String name; |  | ||||||
| 	@Column(length = 0) |  | ||||||
| 	@Schema(description = "Description of the media") |  | ||||||
| 	public String description; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "series parent ID") |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Series.class) |  | ||||||
| 	public Long parentId; |  | ||||||
| 	@Schema(description = "List of Id of the sopecific covers") |  | ||||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class) |  | ||||||
| 	public List<Long> covers = null; |  | ||||||
| } |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| package org.kar.karideo.model; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.FetchType; |  | ||||||
| import jakarta.persistence.ManyToMany; |  | ||||||
| import jakarta.persistence.ManyToOne; |  | ||||||
| import jakarta.persistence.Table; |  | ||||||
|  |  | ||||||
| @Table(name = "series") |  | ||||||
| @DataIfNotExists |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| public class Series extends GenericDataSoftDelete { |  | ||||||
| 	@Column(nullable = false, length = 0) |  | ||||||
| 	@Schema(description = "Name of the media (this represent the title)") |  | ||||||
| 	public String name; |  | ||||||
| 	@Column(length = 0) |  | ||||||
| 	@Schema(description = "Description of the media") |  | ||||||
| 	public String description; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "series parent ID") |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class) |  | ||||||
| 	public Long parentId; |  | ||||||
| 	@Schema(description = "List of Id of the sopecific covers") |  | ||||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class) |  | ||||||
| 	public List<Long> covers = null; |  | ||||||
| } |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| package org.kar.karideo.model; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; |  | ||||||
| import org.kar.archidata.model.Data; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.FetchType; |  | ||||||
| import jakarta.persistence.ManyToMany; |  | ||||||
| import jakarta.persistence.Table; |  | ||||||
|  |  | ||||||
| @Table(name = "type") |  | ||||||
| @DataIfNotExists |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| public class Type extends GenericDataSoftDelete { |  | ||||||
| 	@Column(nullable = false, length = 0) |  | ||||||
| 	@Schema(description = "Name of the media (this represent the title)") |  | ||||||
| 	public String name; |  | ||||||
| 	@Column(length = 0) |  | ||||||
| 	@Schema(description = "Description of the media") |  | ||||||
| 	public String description; |  | ||||||
| 	@Schema(description = "List of Id of the sopecific covers") |  | ||||||
| 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = Data.class) |  | ||||||
| 	public List<Long> covers = null; |  | ||||||
| } |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| package org.kar.karideo.model; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; |  | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.FetchType; |  | ||||||
| import jakarta.persistence.ManyToOne; |  | ||||||
| import jakarta.persistence.Table; |  | ||||||
|  |  | ||||||
| @Table(name = "userMediaAdvancement") |  | ||||||
| @DataIfNotExists |  | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) |  | ||||||
| public class UserMediaAdvancement extends GenericDataSoftDelete { |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "Foreign Key Id of the user") |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = UserKarideo.class) |  | ||||||
| 	public long userId; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "Id of the media") |  | ||||||
| 	@ManyToOne(fetch = FetchType.LAZY, targetEntity = Media.class) |  | ||||||
| 	public long mediaId; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "Percent of admencement in the media") |  | ||||||
| 	public float percent; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "Number of second of admencement in the media") |  | ||||||
| 	public int time; |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Schema(description = "Number of time this media has been read") |  | ||||||
| 	public int count; |  | ||||||
| } |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| package org.kar.karideo.util; |  | ||||||
|  |  | ||||||
| public class ConfigVariable { |  | ||||||
| 	public static final String BASE_NAME = "ORG_KARIDEO_"; |  | ||||||
| 	 |  | ||||||
|     public static String getFrontFolder() { |  | ||||||
|         String out = System.getenv(BASE_NAME + "FRONT_FOLDER"); |  | ||||||
|         if (out == null) { |  | ||||||
|             return "/application/front"; |  | ||||||
|         } |  | ||||||
|         return out; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,10 +1,11 @@ | |||||||
| package test.kar.karideo; | package test.atriasoft.karideo; | ||||||
| 
 | 
 | ||||||
| import java.util.Map; | 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 { | public class Common { | ||||||
| 	static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", Boolean.TRUE))); | 	static String USER_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_user_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", PartRight.READ))); | ||||||
| 	static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", Boolean.TRUE, "ADMIN", Boolean.TRUE))); | 	static String ADMIN_TOKEN = JWTWrapper.createJwtTestToken(16512, "test_admin_login", "KarAuth", "karideo", Map.of("karideo", Map.of("USER", PartRight.READ_WRITE, "ADMIN", PartRight.READ_WRITE))); | ||||||
| } | } | ||||||
							
								
								
									
										115
									
								
								back/test/src/test/atriasoft/karideo/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								back/test/src/test/atriasoft/karideo/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | package test.atriasoft.karideo; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.InternalServerErrorException; | ||||||
|  |  | ||||||
|  | public class ConfigureDb { | ||||||
|  | 	final static private Logger LOGGER = LoggerFactory.getLogger(ConfigureDb.class); | ||||||
|  | 	final static private String modeTestForced = null;// "MONGO"; | ||||||
|  | 	public static DBAccess da = null; | ||||||
|  |  | ||||||
|  | 	public static void configure() throws IOException, InternalServerErrorException, DataAccessException { | ||||||
|  | 		String modeTest = System.getenv("TEST_E2E_MODE"); | ||||||
|  | 		if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "SQLITE-MEMORY"; | ||||||
|  | 		} else if ("true".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "MY-SQL"; | ||||||
|  | 		} | ||||||
|  | 		// override the local test: | ||||||
|  | 		if (modeTestForced != null) { | ||||||
|  | 			modeTest = modeTestForced; | ||||||
|  | 		} | ||||||
|  | 		// for local test: | ||||||
|  | 		ConfigBaseVariable.apiAdress = "http://127.0.0.1:12342/test/api/"; | ||||||
|  | 		// Enable the test mode permit to access to the test token (never use it in production). | ||||||
|  | 		ConfigBaseVariable.testMode = "true"; | ||||||
|  | 		if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = null; | ||||||
|  | 			ConfigBaseVariable.dbHost = "memory"; | ||||||
|  | 			// for test we need to connect all time the DB | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} else if ("SQLITE".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = null; | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} else if ("MY-SQL".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "mysql"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_Karideo_db"; | ||||||
|  | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.dbUser = "root"; | ||||||
|  | 		} else if ("MONGO".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			ConfigBaseVariable.dbType = "mongo"; | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_Karideo_db"; | ||||||
|  | 		} else { | ||||||
|  | 			// User local modification ... | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_Karideo_db"; | ||||||
|  | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.dbUser = "root"; | ||||||
|  | 		} | ||||||
|  | 		removeDB(); | ||||||
|  | 		// Connect the dataBase... | ||||||
|  | 		da = DBAccess.createInterface(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void removeDB() { | ||||||
|  | 		String modeTest = System.getenv("TEST_E2E_MODE"); | ||||||
|  | 		if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "SQLITE-MEMORY"; | ||||||
|  | 		} else if ("true".equalsIgnoreCase(modeTest)) { | ||||||
|  | 			modeTest = "MY-SQL"; | ||||||
|  | 		} | ||||||
|  | 		// override the local test: | ||||||
|  | 		if (modeTestForced != null) { | ||||||
|  | 			modeTest = modeTestForced; | ||||||
|  | 		} | ||||||
|  | 		DbConfig config = null; | ||||||
|  | 		try { | ||||||
|  | 			config = new DbConfig(); | ||||||
|  | 		} catch (final DataAccessException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		config.setDbName(null); | ||||||
|  | 		LOGGER.info("Remove the DB and create a new one '{}'", config.getDbName()); | ||||||
|  | 		try (final DBAccess daRoot = DBAccess.createInterface(config)) { | ||||||
|  | 			if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				// nothing to do ... | ||||||
|  | 			} else if ("SQLITE".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} else if ("MY-SQL".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} else if ("MONGO".equalsIgnoreCase(modeTest)) { | ||||||
|  | 				daRoot.deleteDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 			} | ||||||
|  | 			daRoot.createDB(ConfigBaseVariable.bdDatabase); | ||||||
|  | 		} catch (final InternalServerErrorException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} catch (final IOException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 			LOGGER.error("Fail to clean the DB"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void clear() throws IOException { | ||||||
|  | 		LOGGER.info("Remove the test db"); | ||||||
|  | 		removeDB(); | ||||||
|  | 		// The connection is by default open ==> close it at the end of test: | ||||||
|  | 		da.close(); | ||||||
|  | 		DbIoFactory.closeAllForceMode(); | ||||||
|  | 		ConfigBaseVariable.clearAllValue(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package test.kar.karideo; | package test.atriasoft.karideo; | ||||||
| 
 | 
 | ||||||
| import org.junit.jupiter.api.extension.ConditionEvaluationResult; | import org.junit.jupiter.api.extension.ConditionEvaluationResult; | ||||||
| import org.junit.jupiter.api.extension.ExecutionCondition; | import org.junit.jupiter.api.extension.ExecutionCondition; | ||||||
							
								
								
									
										48
									
								
								back/test/src/test/atriasoft/karideo/TestBase.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								back/test/src/test/atriasoft/karideo/TestBase.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | package test.atriasoft.karideo; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.AfterAll; | ||||||
|  | import org.junit.jupiter.api.BeforeAll; | ||||||
|  | import org.junit.jupiter.api.MethodOrderer; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.api.TestMethodOrder; | ||||||
|  | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
|  | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.atriasoft.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/"; | ||||||
|  |  | ||||||
|  | 	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("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(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public static void TestEmpty() throws Exception { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| package test.kar.karideo; | package test.atriasoft.karideo; | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| 
 | 
 | ||||||
|  | import org.atriasoft.archidata.exception.RESTErrorResponseException; | ||||||
|  | import org.atriasoft.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.atriasoft.archidata.tools.RESTApi; | ||||||
|  | import org.atriasoft.karideo.api.HealthCheck.HealthResult; | ||||||
| import org.junit.jupiter.api.AfterAll; | import org.junit.jupiter.api.AfterAll; | ||||||
| import org.junit.jupiter.api.Assertions; | import org.junit.jupiter.api.Assertions; | ||||||
| import org.junit.jupiter.api.BeforeAll; | import org.junit.jupiter.api.BeforeAll; | ||||||
| @@ -10,11 +12,6 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.exception.RESTErrorResponseExeption; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.kar.archidata.tools.RESTApi; |  | ||||||
| import org.kar.karideo.api.HealthCheck.HealthResult; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
| @@ -28,43 +25,36 @@ public class TestHealthCheck { | |||||||
| 
 | 
 | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
|  | 		ConfigureDb.configure(); | ||||||
| 		LOGGER.info("configure server ..."); | 		LOGGER.info("configure server ..."); | ||||||
| 		webInterface = new WebLauncherTest(); | 		webInterface = new WebLauncherTest(); | ||||||
| 		LOGGER.info("Create DB"); |  | ||||||
| 		try { |  | ||||||
| 			webInterface.migrateDB(); |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			ex.printStackTrace(); |  | ||||||
| 			LOGGER.error("Detect an error: {}", ex.getMessage()); |  | ||||||
| 		} |  | ||||||
| 		LOGGER.info("Start REST (BEGIN)"); | 		LOGGER.info("Start REST (BEGIN)"); | ||||||
| 		webInterface.process(); | 		webInterface.process(); | ||||||
| 		LOGGER.info("Start REST (DONE)"); | 		LOGGER.info("Start REST (DONE)"); | ||||||
| 		api = new RESTApi(ConfigBaseVariable.apiAdress); | 		api = new RESTApi(ConfigBaseVariable.apiAdress); | ||||||
|  | 		api.setToken(Common.ADMIN_TOKEN); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void stopWebServer() throws InterruptedException, IOException { | 	public static void stopWebServer() throws Exception { | ||||||
| 		LOGGER.info("Kill the web server"); | 		LOGGER.info("Kill the web server"); | ||||||
| 		webInterface.stop(); | 		webInterface.stop(); | ||||||
| 		webInterface = null; | 		webInterface = null; | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
| 	@Test | 	@Test | ||||||
| 	//@RepeatedTest(10) | 	// @RepeatedTest(10) | ||||||
| 	public void checkHealthCheck() throws Exception { | 	public void checkHealthCheck() throws Exception { | ||||||
| 		final HealthResult result = api.get(HealthResult.class, "health_check"); | 		final HealthResult result = api.request("health_check").get().fetch(HealthResult.class); | ||||||
| 		Assertions.assertEquals(result.value(), "alive and kicking"); | 		Assertions.assertEquals(result.value(), "alive and kicking"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Order(2) | 	@Order(2) | ||||||
| 	@Test | 	@Test | ||||||
| 	public void checkHealthCheckWrongAPI() throws Exception { | 	public void checkHealthCheckWrongAPI() throws Exception { | ||||||
| 		Assertions.assertThrows(RESTErrorResponseExeption.class, () -> api.get(HealthResult.class, "health_checks")); | 		Assertions.assertThrows(RESTErrorResponseException.class, () -> api.request("health_check_kaboom").get().fetch()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
							
								
								
									
										12
									
								
								back/test/src/test/atriasoft/karideo/WebLauncherTest.java
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								back/test/src/test/atriasoft/karideo/WebLauncherTest.java
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  |  | ||||||
|  | package test.atriasoft.karideo; | ||||||
|  |  | ||||||
|  | import org.atriasoft.karideo.WebLauncher; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class WebLauncherTest extends WebLauncher { | ||||||
|  | 	final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class); | ||||||
|  |  | ||||||
|  | 	public WebLauncherTest() {} | ||||||
|  | } | ||||||
| @@ -1,28 +0,0 @@ | |||||||
|  |  | ||||||
| package test.kar.karideo; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.kar.karideo.WebLauncher; |  | ||||||
| import org.slf4j.Logger; |  | ||||||
| import org.slf4j.LoggerFactory; |  | ||||||
|  |  | ||||||
| public class WebLauncherTest extends WebLauncher { |  | ||||||
| 	final private static Logger LOGGER = LoggerFactory.getLogger(WebLauncherTest.class); |  | ||||||
| 	 |  | ||||||
| 	public WebLauncherTest() { |  | ||||||
| 		LOGGER.debug("Configure REST system"); |  | ||||||
| 		// for local test: |  | ||||||
| 		ConfigBaseVariable.apiAdress = "http://127.0.0.1:12345/test/api/"; |  | ||||||
| 		ConfigBaseVariable.testMode = "true"; |  | ||||||
| 		//ConfigBaseVariable.dbPort = "3306"; |  | ||||||
| 		// for the test we a in memory sqlite.. |  | ||||||
| 		ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 		ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 		// for test we need to connect all time the DB |  | ||||||
| 		ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		 |  | ||||||
| 		//ConfigBaseVariable.dbHost = "localhost"; |  | ||||||
| 		//ConfigBaseVariable.dbUser = "root"; |  | ||||||
| 		//ConfigBaseVariable.dbPassword = "ZERTYSDGFVHSDFGHJYZSDFGSQxfgsqdfgsqdrf4564654"; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										1
									
								
								front/.env
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								front/.env
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | NODE_ENV=development | ||||||
							
								
								
									
										2
									
								
								front/.env.production
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								front/.env.production
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | # URL for database connection | ||||||
|  | VITE_API_BASE_URL=karideo/api/ | ||||||
							
								
								
									
										27
									
								
								front/.storybook/main.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								front/.storybook/main.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | import type { StorybookConfig } from '@storybook/react-vite'; | ||||||
|  |  | ||||||
|  | const config: StorybookConfig = { | ||||||
|  |   framework: { | ||||||
|  |     name: '@storybook/react-vite', | ||||||
|  |     options: {}, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   core: { | ||||||
|  |     disableTelemetry: true, | ||||||
|  |     builder: '@storybook/builder-vite', | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   stories: ['../src/**/*.@(mdx|stories.@(js|jsx|ts|tsx))'], | ||||||
|  |  | ||||||
|  |   addons: ['@storybook/addon-links', '@storybook/addon-essentials'], | ||||||
|  |  | ||||||
|  |   staticDirs: ['../public'], | ||||||
|  |  | ||||||
|  |   typescript: { | ||||||
|  |     reactDocgen: false, | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   docs: {}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default config; | ||||||
							
								
								
									
										16
									
								
								front/.storybook/preview-head.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								front/.storybook/preview-head.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | <style> | ||||||
|  |   html { | ||||||
|  |     background: transparent !important; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .docs-story > :first-child { | ||||||
|  |     padding: 0; | ||||||
|  |   } | ||||||
|  |   .docs-story > * { | ||||||
|  |     background: transparent !important; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   #root #start-ui-storybook-wrapper { | ||||||
|  |     min-height: 100vh; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
							
								
								
									
										34
									
								
								front/.storybook/preview.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								front/.storybook/preview.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import React from 'react'; | ||||||
|  |  | ||||||
|  | import { Box } from '@chakra-ui/react'; | ||||||
|  | import { ChakraProvider } from '@chakra-ui/react'; | ||||||
|  | import { MemoryRouter } from 'react-router-dom'; | ||||||
|  |  | ||||||
|  | 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"> | ||||||
|  |       {children} | ||||||
|  |     </Box> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const decorators = [ | ||||||
|  |   (Story, context) => ( | ||||||
|  |     <ColorModeProvider> | ||||||
|  |       <ChakraProvider value={systemTheme}> | ||||||
|  |         {/* Using MemoryRouter to avoid route clashing with Storybook */} | ||||||
|  |         <MemoryRouter> | ||||||
|  |           <DocumentationWrapper> | ||||||
|  |             <Story {...context} /> | ||||||
|  |           </DocumentationWrapper> | ||||||
|  |         </MemoryRouter> | ||||||
|  |         <Toaster /> | ||||||
|  |       </ChakraProvider> | ||||||
|  |     </ColorModeProvider> | ||||||
|  |   ), | ||||||
|  | ]; | ||||||
							
								
								
									
										2
									
								
								front/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								front/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | Proprietary | ||||||
|  | @copyright Edouard Dupin 2024 | ||||||
| @@ -1,134 +0,0 @@ | |||||||
| { |  | ||||||
|   "$schema" : "./node_modules/@angular/cli/lib/config/schema.json", |  | ||||||
|   "version" : 1, |  | ||||||
|   "newProjectRoot" : "projects", |  | ||||||
|   "defaultProject" : "karideo", |  | ||||||
|   "projects" : { |  | ||||||
|     "karideo" : { |  | ||||||
|       "root" : "", |  | ||||||
|       "sourceRoot" : "src", |  | ||||||
|       "projectType" : "application", |  | ||||||
|       "architect" : { |  | ||||||
|         "build" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:browser", |  | ||||||
|           "options" : { |  | ||||||
|             "outputPath" : "dist", |  | ||||||
|             "index" : "src/index.html", |  | ||||||
|             "main" : "src/main.ts", |  | ||||||
|             "tsConfig" : "src/tsconfig.app.json", |  | ||||||
|             "polyfills" : "src/polyfills.ts", |  | ||||||
|             "assets" : [ "src/assets", "src/favicon.ico" ], |  | ||||||
|             "styles" : [ "src/styles.less", "src/generic_page.less", "src/theme.color.blue.less", "src/theme.checkbox.less", "src/theme.modal.less" ], |  | ||||||
|             "scripts" : [ ] |  | ||||||
|           }, |  | ||||||
|           "configurations" : { |  | ||||||
|             "production" : { |  | ||||||
|               "optimization" : true, |  | ||||||
|               "outputHashing" : "all", |  | ||||||
|               "sourceMap" : false, |  | ||||||
|               "namedChunks" : false, |  | ||||||
|               "aot" : true, |  | ||||||
|               "extractLicenses" : true, |  | ||||||
|               "vendorChunk" : false, |  | ||||||
|               "buildOptimizer" : true, |  | ||||||
|               "fileReplacements" : [ { |  | ||||||
|                 "replace" : "src/environments/environment.ts", |  | ||||||
|                 "with" : "src/environments/environment.prod.ts" |  | ||||||
|               } ] |  | ||||||
|             }, |  | ||||||
|             "develop" : { |  | ||||||
|               "optimization" : false, |  | ||||||
|               "outputHashing" : "none", |  | ||||||
|               "sourceMap" : true, |  | ||||||
|               "namedChunks" : true, |  | ||||||
|               "aot" : true, |  | ||||||
|               "extractLicenses" : true, |  | ||||||
|               "vendorChunk" : true, |  | ||||||
|               "buildOptimizer" : false |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "serve" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:dev-server", |  | ||||||
|           "options" : { |  | ||||||
|             "browserTarget" : "karideo:build" |  | ||||||
|           }, |  | ||||||
|           "configurations" : { |  | ||||||
|             "production" : { |  | ||||||
|               "browserTarget" : "karideo:build:production" |  | ||||||
|             }, |  | ||||||
|             "develop" : { |  | ||||||
|               "browserTarget" : "karideo:build:develop" |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "extract-i18n" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:extract-i18n", |  | ||||||
|           "options" : { |  | ||||||
|             "browserTarget" : "karideo:build" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "test" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:karma", |  | ||||||
|           "options" : { |  | ||||||
|             "main" : "src/test.ts", |  | ||||||
|             "karmaConfig" : "./karma.conf.js", |  | ||||||
|             "polyfills" : "src/polyfills.ts", |  | ||||||
|             "tsConfig" : "src/tsconfig.spec.json", |  | ||||||
|             "scripts" : [ ], |  | ||||||
|             "styles" : [ "src/styles.less", "src/generic_page.less", "src/theme.color.blue.less", "src/theme.checkbox.less", "src/theme.modal.less" ], |  | ||||||
|             "assets" : [ "src/assets", "src/favicon.ico" ] |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "lint" : { |  | ||||||
|           "builder" : "@angular-eslint/builder:lint", |  | ||||||
|           "options" : { |  | ||||||
|             "fix": true, |  | ||||||
|             "eslintConfig": ".eslintrc.js", |  | ||||||
|             "lintFilePatterns": [ |  | ||||||
|               "src/**/*.spec.ts", |  | ||||||
|               "src/**/*.ts" |  | ||||||
|             ] |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "TTTTTTlint" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:tslint", |  | ||||||
|           "options" : { |  | ||||||
|             "tsConfig" : [ "src/tsconfig.app.json", "src/tsconfig.spec.json" ], |  | ||||||
|             "exclude" : [ "**/node_modules/**" ] |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "karideo-e2e" : { |  | ||||||
|       "root" : "e2e", |  | ||||||
|       "sourceRoot" : "e2e", |  | ||||||
|       "projectType" : "application", |  | ||||||
|       "architect" : { |  | ||||||
|         "e2e" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:protractor", |  | ||||||
|           "options" : { |  | ||||||
|             "protractorConfig" : "./protractor.conf.js", |  | ||||||
|             "devServerTarget" : "karideo:serve" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "lint" : { |  | ||||||
|           "builder" : "@angular-devkit/build-angular:tslint", |  | ||||||
|           "options" : { |  | ||||||
|             "tsConfig" : [ "e2e/tsconfig.e2e.json" ], |  | ||||||
|             "exclude" : [ "**/node_modules/**" ] |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   "schematics" : { |  | ||||||
|     "@schematics/angular:component" : { |  | ||||||
|       "prefix" : "app", |  | ||||||
|       "style" : "less" |  | ||||||
|     }, |  | ||||||
|     "@schematics/angular:directive" : { |  | ||||||
|       "prefix" : "app" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										10637
									
								
								front/config sample.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10637
									
								
								front/config sample.yaml
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								front/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								front/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <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>Karideo</title> | ||||||
|  |     <link rel="icon" href="/favicon.ico" /> | ||||||
|  |   </head> | ||||||
|  |   <body style="width:100vw;height:100vh;min-width:100%;min-height:100%;"> | ||||||
|  |     <div id="root" style="width:100%;height:100%;min-width:100%;min-height:100%;"></div> | ||||||
|  |     <script type="module" src="/src/main.tsx"></script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										9
									
								
								front/knip.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								front/knip.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | import type { KnipConfig } from 'knip'; | ||||||
|  |  | ||||||
|  | const config: KnipConfig = { | ||||||
|  |   // Ignoring mostly shell binaries | ||||||
|  |   ignoreBinaries: ['export', 'sleep'], | ||||||
|  |   ignore: [], | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default config; | ||||||
							
								
								
									
										21757
									
								
								front/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										21757
									
								
								front/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,41 +1,89 @@ | |||||||
| { | { | ||||||
| 	"name": "karideo", |   "name": "karideo", | ||||||
| 	"version": "0.0.0", |   "private": true, | ||||||
| 	"license": "MPL-2", |   "version": "0.0.1", | ||||||
| 	"scripts": { |   "description": "KAR web music application", | ||||||
| 		"all": "npm run build && npm run test", |   "author": { | ||||||
| 		"ng": "ng", |     "name": "Edouard DUPIN", | ||||||
| 		"dev": "ng serve --configuration=develop --watch --port 4202", |     "email": "yui.heero@gmail.farm" | ||||||
| 		"build": "ng build --prod", |   }, | ||||||
| 		"test": "ng test", |   "license": "PROPRIETARY", | ||||||
| 		"lint": "ng lint", |   "engines": { | ||||||
| 		"style": "prettier --write .", |     "node": ">=20" | ||||||
| 		"e2e": "ng e2e" |   }, | ||||||
| 	}, |   "scripts": { | ||||||
| 	"private": true, |     "update_packages": "ncu --target minor", | ||||||
| 	"dependencies": { |     "upgrade_packages": "ncu --upgrade ", | ||||||
| 		"@angular/animations": "^14.2.10", |     "install_dependency": "pnpm install", | ||||||
| 		"@angular/cdk": "^14.2.7", |     "test": "vitest run", | ||||||
| 		"@angular/common": "^14.2.10", |     "test:watch": "vitest watch", | ||||||
| 		"@angular/compiler": "^14.2.10", |     "build": "tsc && vite build", | ||||||
| 		"@angular/core": "^14.2.10", |     "static:build": "pnpm build", | ||||||
| 		"@angular/forms": "^14.2.10", |     "dev": "vite", | ||||||
| 		"@angular/material": "^14.2.7", |     "pretty": "prettier -w .", | ||||||
| 		"@angular/platform-browser": "^14.2.10", |     "lint": "pnpm tsc --noEmit", | ||||||
| 		"@angular/platform-browser-dynamic": "^14.2.10", |     "storybook": "storybook dev -p 3001", | ||||||
| 		"@angular/router": "^14.2.10", |     "storybook:build": "storybook build && mv ./storybook-static ./public/storybook" | ||||||
| 		"rxjs": "^7.5.7", |   }, | ||||||
| 		"zone.js": "^0.12.0" |   "lint-staged": { | ||||||
| 	}, |     "*.{ts,tsx,js,jsx,json}": "prettier --write" | ||||||
| 	"devDependencies": { |   }, | ||||||
| 		"@angular-devkit/build-angular": "^14.2.9", |   "dependencies": { | ||||||
| 		"@angular-eslint/builder": "14.2.0", |     "react-speech-recognition": "4.0.1", | ||||||
| 		"@angular-eslint/eslint-plugin": "14.2.0", |     "regenerator-runtime": "0.14.1", | ||||||
| 		"@angular-eslint/eslint-plugin-template": "14.2.0", |     "@locator/babel-jsx": "0.4.4", | ||||||
| 		"@angular-eslint/schematics": "14.2.0", |     "@trivago/prettier-plugin-sort-imports": "5.2.2", | ||||||
| 		"@angular-eslint/template-parser": "14.2.0", |     "@chakra-ui/cli": "3.27.1", | ||||||
| 		"@angular/cli": "^14.2.9", |     "@chakra-ui/react": "3.27.1", | ||||||
| 		"@angular/compiler-cli": "^14.2.10", |     "@emotion/react": "11.14.0", | ||||||
| 		"@angular/language-service": "^14.2.10" |     "allotment": "1.20.4", | ||||||
| 	} |     "css-mediaquery": "0.1.2", | ||||||
|  |     "dayjs": "1.11.18", | ||||||
|  |     "history": "5.3.0", | ||||||
|  |     "next-themes": "^0.4.6", | ||||||
|  |     "react": "19.2.0", | ||||||
|  |     "react-dom": "19.2.0", | ||||||
|  |     "react-error-boundary": "6.0.0", | ||||||
|  |     "react-icons": "5.5.0", | ||||||
|  |     "react-router-dom": "7.9.4", | ||||||
|  |     "react-select": "5.10.2", | ||||||
|  |     "react-use": "17.6.0", | ||||||
|  |     "zod": "4.1.12", | ||||||
|  |     "zustand": "5.0.8" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@chakra-ui/styled-system": "^2.12.0", | ||||||
|  |     "@playwright/test": "1.56.1", | ||||||
|  |     "@storybook/addon-links": "9.1.13", | ||||||
|  |     "@storybook/react-vite": "9.1.13", | ||||||
|  |     "@testing-library/jest-dom": "6.9.1", | ||||||
|  |     "@testing-library/react": "16.3.0", | ||||||
|  |     "@testing-library/user-event": "14.6.1", | ||||||
|  |     "@trivago/prettier-plugin-sort-imports": "5.2.2", | ||||||
|  |     "@types/jest": "30.0.0", | ||||||
|  |     "@types/node": "24.8.1", | ||||||
|  |     "@types/react": "19.2.2", | ||||||
|  |     "@types/react-dom": "19.2.2", | ||||||
|  |     "@typescript-eslint/eslint-plugin": "8.46.1", | ||||||
|  |     "@typescript-eslint/parser": "8.46.1", | ||||||
|  |     "@vitejs/plugin-react": "5.0.4", | ||||||
|  |     "eslint": "9.38.0", | ||||||
|  |     "eslint-plugin-import": "2.32.0", | ||||||
|  |     "eslint-plugin-react": "7.37.5", | ||||||
|  |     "eslint-plugin-react-hooks": "7.0.0", | ||||||
|  |     "eslint-plugin-storybook": "9.1.13", | ||||||
|  |     "jest": "30.2.0", | ||||||
|  |     "jest-environment-jsdom": "30.2.0", | ||||||
|  |     "knip": "5.66.0", | ||||||
|  |     "lint-staged": "16.2.4", | ||||||
|  |     "npm-check-updates": "^19.1.1", | ||||||
|  |     "prettier": "3.6.2", | ||||||
|  |     "puppeteer": "24.25.0", | ||||||
|  |     "react-is": "19.2.0", | ||||||
|  |     "storybook": "9.1.13", | ||||||
|  |     "ts-node": "10.9.2", | ||||||
|  |     "typescript": "5.9.3", | ||||||
|  |     "vite": "7.1.10", | ||||||
|  |     "vitest": "3.2.4" | ||||||
|  |   } | ||||||
| } | } | ||||||
							
								
								
									
										11995
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										11995
									
								
								front/pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								front/prettier.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								front/prettier.config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // Using a JS file, allowing us to add comments | ||||||
|  | module.exports = { | ||||||
|  |   // This plugins line is mandatory for the plugin to work with pnpm. | ||||||
|  |   // https://github.com/trivago/prettier-plugin-sort-imports/blob/61d069711008c530f5a41ca4e254781abc5de358/README.md?plain=1#L89-L96 | ||||||
|  |   plugins: ['@trivago/prettier-plugin-sort-imports'], | ||||||
|  |   endOfLine: 'lf', | ||||||
|  |   semi: true, | ||||||
|  |   singleQuote: true, | ||||||
|  |   tabWidth: 2, | ||||||
|  |   trailingComma: 'es5', | ||||||
|  |   arrowParens: 'always', | ||||||
|  |   importOrder: ['^react$', '^(?!^react$|^@/|^[./]).*', '^@/(.*)$', '^[./]'], | ||||||
|  |   importOrderSeparation: true, | ||||||
|  |   importOrderSortSpecifiers: true, | ||||||
|  |   importOrderParserPlugins: ['jsx', 'typescript'], | ||||||
|  | }; | ||||||
| Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											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" | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								front/src/App.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								front/src/App.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | import { ErrorBoundary } from '@/errors/ErrorBoundary'; | ||||||
|  |  | ||||||
|  | import { VideoPlayer } from './components'; | ||||||
|  | import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment'; | ||||||
|  | import { AppRoutes } from './scene/AppRoutes'; | ||||||
|  | import { ServiceContextProvider } from './service/ServiceContext'; | ||||||
|  |  | ||||||
|  | export const App = () => { | ||||||
|  |   return ( | ||||||
|  |     <ServiceContextProvider> | ||||||
|  |       <EnvDevelopment /> | ||||||
|  |       <ErrorBoundary> | ||||||
|  |         <AppRoutes /> | ||||||
|  |       </ErrorBoundary> | ||||||
|  |       <VideoPlayer /> | ||||||
|  |     </ServiceContextProvider> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default App; | ||||||
| @@ -1,15 +0,0 @@ | |||||||
|  |  | ||||||
| <!-- Generig global menu --> |  | ||||||
| <app-top-menu [menu]="currentMenu" (callback)="eventOnMenu($event)"></app-top-menu> |  | ||||||
| <!-- all interfaced pages --> |  | ||||||
| <div class="main-content" *ngIf="autoConnectedDone"> |  | ||||||
| 	<router-outlet ></router-outlet> |  | ||||||
| </div> |  | ||||||
| <div class="main-content" *ngIf="!autoConnectedDone"> |  | ||||||
| 	<div class="generic-page"> |  | ||||||
| 		<div class="fill-all colomn_mutiple"> |  | ||||||
| 			<b style="color:red;">Auto-connection in progress</b> |  | ||||||
| 			<div class="clear"></div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @@ -1,19 +0,0 @@ | |||||||
|  |  | ||||||
| <div class="imgContainer-small"> |  | ||||||
| 	<div *ngIf="covers"> |  | ||||||
| 		<!--<data-image id="{{cover}}"></data-image>--> |  | ||||||
| 		<img src="{{covers[0]}}"/> |  | ||||||
| 	</div> |  | ||||||
| 	<div *ngIf="!covers" class="noImage"> |  | ||||||
| 		 |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| <div class="season-small"> |  | ||||||
| 	Season {{numberSeason}} |  | ||||||
| </div> |  | ||||||
| <div class="description-small" *ngIf="count > 1"> |  | ||||||
| 	{{count}} Episodes |  | ||||||
| </div> |  | ||||||
| <div class="description-small" *ngIf="count == 1"> |  | ||||||
| 	{{count}} Episode |  | ||||||
| </div> |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| <div> |  | ||||||
| 	<div class="count-base"> |  | ||||||
| 		<div class="count" *ngIf="countvideo"> |  | ||||||
| 			{{countvideo}} |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="imgContainer-small"> |  | ||||||
| 		<div *ngIf="covers"> |  | ||||||
| 			<!--<data-image id="{{cover}}"></data-image>--> |  | ||||||
| 			<img src="{{covers[0]}}"/> |  | ||||||
| 		</div> |  | ||||||
| 		<div *ngIf="!covers" class="noImage"> |  | ||||||
| 			 |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="title-small"> |  | ||||||
| 		{{name}} |  | ||||||
| 	</div> |  | ||||||
| 	<!--  |  | ||||||
| 	<div class="description-small" *ngIf="description"> |  | ||||||
| 		{{description}} |  | ||||||
| 	</div> |  | ||||||
| 	--> |  | ||||||
| </div> |  | ||||||
| @@ -1,18 +0,0 @@ | |||||||
| <div> |  | ||||||
| 	<div class="count-base"> |  | ||||||
| 		<span class="count" *ngIf="countvideo"> |  | ||||||
| 			{{countvideo}} |  | ||||||
| 		</span> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="imgContainer-small"> |  | ||||||
| 		<div *ngIf="covers"> |  | ||||||
| 			<img src="{{covers[0]}}" class="miniature-small"/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="title-small"> |  | ||||||
| 		{{name}} |  | ||||||
| 	</div> |  | ||||||
| 	<div class="description-small" *ngIf="description"> |  | ||||||
| 		{{description}} |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| <div> |  | ||||||
| 	<div class="count-base"> |  | ||||||
| 		<span class="views" *ngIf="advancement"> |  | ||||||
| 			{{advancement.count}} |  | ||||||
| 		</span> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="videoImgContainer"> |  | ||||||
| 		<div *ngIf="covers"> |  | ||||||
| 			<!--<data-image id="{{cover}}"></data-image>--> |  | ||||||
| 			<img src="{{covers[0]}}" /> |  | ||||||
| 		</div> |  | ||||||
| 		<div *ngIf="!covers" class="noImage"> |  | ||||||
|  |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="view-progess" [ngStyle]="updateAdvancement()"></div> |  | ||||||
| 	<div class="title-small" *ngIf="data"> |  | ||||||
| 		{{episodeDisplay}} {{name}} |  | ||||||
| 	</div> |  | ||||||
| 	<div class="title-small" *ngIf="!data"> |  | ||||||
| 		Error media: {{element?.id}} |  | ||||||
| 	</div> |  | ||||||
| 	<!-- |  | ||||||
| 	<div class="description-small" *ngIf="description"> |  | ||||||
| 		{{description}} |  | ||||||
| 	</div> |  | ||||||
| 	--> |  | ||||||
| </div> |  | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| import { Media, isMedia } from "./media"; |  | ||||||
|  |  | ||||||
| export { |  | ||||||
|     Media, isMedia, |  | ||||||
| } |  | ||||||
| @@ -1,47 +0,0 @@ | |||||||
| import { isNumberFinite, isString, isOptionalOf } from "common/utils"; |  | ||||||
| import { isNodeData, NodeData } from "common/model/node"; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  export interface Media extends NodeData { |  | ||||||
|     dataId?: number; |  | ||||||
|     typeId?: number; |  | ||||||
|     seriesId?: number; |  | ||||||
|     seasonId?: number; |  | ||||||
|     episode?: number; |  | ||||||
|     date?: number; |  | ||||||
|     time?: number; |  | ||||||
|     ageLimit?: number; |  | ||||||
|  }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export function isMedia(data: any): data is Media { |  | ||||||
|     if (!isNodeData(data) as any) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.dataId, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.typeId, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.seriesId, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.seasonId, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.episode, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.date, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.time, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isOptionalOf(data.ageLimit, isNumberFinite)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| import { isNumberFinite, isString, isOptionalOf, isNumber } from "common/utils"; |  | ||||||
| import { isNodeData, NodeData } from "common/model/node"; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export interface UserMediaAdvancement { |  | ||||||
|     id: number; |  | ||||||
|  |  | ||||||
|     // Id of the media |  | ||||||
|     mediaId?: number; |  | ||||||
|     // Percent of advancement in the media |  | ||||||
|     percent?: number; |  | ||||||
|     // "Number of second of advancement in the media |  | ||||||
|     time?: number; |  | ||||||
|     // Number of time this media has been read |  | ||||||
|     count?: number; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| export function isUserMediaAdvancement(data: any): data is UserMediaAdvancement { |  | ||||||
|     if (!isNumberFinite(data.id)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isNumberFinite(data.mediaId)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isNumber(data.percent)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isNumberFinite(data.time)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     if (!isNumberFinite(data.count)) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| <div class="generic-page"> |  | ||||||
| 	<div class="title"> |  | ||||||
| 		Karideo |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all colomn_mutiple"> |  | ||||||
| 		<div *ngFor="let data of dataList" class="item-home" (click)="onSelectType($event, data.id)" (auxclick)="onSelectType($event, data.id)"> |  | ||||||
| 			<app-element-type [element]="data"></app-element-type> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @@ -1,140 +0,0 @@ | |||||||
| <div class="main-reduce edit-page"> |  | ||||||
| 	<div class="title"> |  | ||||||
| 		Edit season |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsRemoved"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The season has been removed |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsNotFound"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The season does not exist |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsLoading"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			Loading ...<br/>  |  | ||||||
| 			Please wait. |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Number: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="number" |  | ||||||
| 				       placeholder="Id of the season" |  | ||||||
| 				       [value]="numberVal" |  | ||||||
| 				       (input)="onNumber($event.target.value)" |  | ||||||
| 				       /> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Description: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="text" |  | ||||||
| 				       placeholder="Description of the Media" |  | ||||||
| 				       [value]="description" |  | ||||||
| 				       (input)="onDescription($event.target.value)"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="send_value"> |  | ||||||
| 			<button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- Cover section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Covers |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="hide-element"> |  | ||||||
| 			<input type="file"  |  | ||||||
| 	 			   #fileInput |  | ||||||
| 			       (change)="onChangeCover($event.target)" |  | ||||||
| 			       placeholder="Select a cover file" |  | ||||||
| 			       accept=".png,.jpg,.jpeg,.webp"/> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<div class="cover" *ngFor="let element of coversDisplay"> |  | ||||||
| 					<div class="cover-image">  |  | ||||||
| 						<img src="{{element.url}}"/> |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="removeCover(element.id)"> |  | ||||||
| 							<i class="material-icons button-remove">highlight_off</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="cover"> |  | ||||||
| 					<div class="cover-no-image">  |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="fileInput.click()"> |  | ||||||
| 							<i class="material-icons button-add">add_circle_outline</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- ADMIN section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Administration |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">data_usage</i> ID: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{idSeason}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Videos: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{videoCount}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">delete_forever</i> Trash: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input" *ngIf="(videoCount == '0')"> |  | ||||||
| 				<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit"> |  | ||||||
| 					<i class="material-icons">delete</i> Remove season |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input" *ngIf="(videoCount != '0')"> |  | ||||||
| 				<i class="material-icons">new_releases</i> Can not remove season, video depending on it |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| <upload-progress [mediaTitle]="upload.labelMediaTitle" |  | ||||||
| 	[mediaUploaded]="upload.mediaSendSize" |  | ||||||
| 	[mediaSize]="upload.mediaSize" |  | ||||||
| 	[result]="upload.result" |  | ||||||
| 	[error]="upload.error"></upload-progress> |  | ||||||
| <delete-confirm |  | ||||||
| 	[comment]="confirmDeleteComment" |  | ||||||
| 	[imageUrl]=confirmDeleteImageUrl |  | ||||||
|     (callback)="deleteConfirmed()"></delete-confirm> |  | ||||||
| @@ -1,29 +0,0 @@ | |||||||
| <div class="generic-page"> |  | ||||||
| 	<div class="fill-title colomn_mutiple"> |  | ||||||
| 		<div class="cover-area"> |  | ||||||
| 			<div class="cover" *ngIf="cover != null" > |  | ||||||
| 				<img src="{{cover}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> |  | ||||||
| 			<div *ngIf="seriesName" class="title"> |  | ||||||
| 				{{seriesName}} |  | ||||||
| 			</div> |  | ||||||
| 			<div class="sub-title-main"> |  | ||||||
| 				Season {{name}} |  | ||||||
| 			</div> |  | ||||||
| 			<div class="description" *ngIf="description"> |  | ||||||
| 				{{description}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-content colomn_mutiple"> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="title" *ngIf="videos.length > 1">Videos:</div> |  | ||||||
| 		<div class="title" *ngIf="videos.length == 1">Video:</div> |  | ||||||
| 		<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)"> |  | ||||||
| 			<app-element-video [element]="data"></app-element-video> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @@ -1,162 +0,0 @@ | |||||||
| <div class="main-reduce  edit-page"> |  | ||||||
| 	<div class="title"> |  | ||||||
| 		Edit series |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsRemoved"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The series has been removed |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsNotFound"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The series does not exist |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsLoading"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			Loading ...<br/>  |  | ||||||
| 			Please wait. |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Type: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<select [ngModel]="typeId" |  | ||||||
| 				        (ngModelChange)="onChangeType($event)"> |  | ||||||
| 					<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 				</select> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Name: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="text" |  | ||||||
| 				       placeholder="Name of the Series" |  | ||||||
| 				       [value]="name" |  | ||||||
| 				       (input)="onName($event.target.value)" |  | ||||||
| 				       /> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Description: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="text" |  | ||||||
| 				       placeholder="Description of the Media" |  | ||||||
| 				       [value]="description" |  | ||||||
| 				       (input)="onDescription($event.target.value)"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="send_value"> |  | ||||||
| 			<button class="button fill-x color-button-validate color-shadow-black" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- Cover section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Covers |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="hide-element"> |  | ||||||
| 			<input type="file"  |  | ||||||
| 	 			   #fileInput |  | ||||||
| 			       (change)="onChangeCover($event.target)" |  | ||||||
| 			       placeholder="Select a cover file" |  | ||||||
| 			       accept=".png,.jpg,.jpeg,.webp"/> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<div class="cover" *ngFor="let element of coversDisplay"> |  | ||||||
| 					<div class="cover-image">  |  | ||||||
| 						<img src="{{element.url}}"/> |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="removeCover(element.id)"> |  | ||||||
| 							<i class="material-icons button-remove">highlight_off</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="cover"> |  | ||||||
| 					<div class="cover-no-image">  |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="fileInput.click()"> |  | ||||||
| 							<i class="material-icons button-add">add_circle_outline</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- ADMIN section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Administration |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">data_usage</i> ID: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{idSeries}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Seasons: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{seasonsCount}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Videos: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{videoCount}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">delete_forever</i> Trash: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input" *ngIf="(videoCount == '0' && seasonsCount == '0')"> |  | ||||||
| 				<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit"> |  | ||||||
| 					<i class="material-icons">delete</i> Remove Series |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input" *ngIf="(videoCount != '0' || seasonsCount != '0')"> |  | ||||||
| 				<i class="material-icons">new_releases</i> Can not remove season or video depending on it |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
|  |  | ||||||
| <upload-progress [mediaTitle]="upload.labelMediaTitle" |  | ||||||
| 	[mediaUploaded]="upload.mediaSendSize" |  | ||||||
| 	[mediaSize]="upload.mediaSize" |  | ||||||
| 	[result]="upload.result" |  | ||||||
| 	[error]="upload.error"></upload-progress> |  | ||||||
| <delete-confirm |  | ||||||
| 	[comment]="confirmDeleteComment" |  | ||||||
| 	[imageUrl]=confirmDeleteImageUrl |  | ||||||
|     (callback)="deleteConfirmed()"></delete-confirm> |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| <div class="generic-page"> |  | ||||||
| 	<div class="fill-title colomn_mutiple"> |  | ||||||
| 		<div class="cover-area"> |  | ||||||
| 			<div class="cover" *ngIf="cover != null" > |  | ||||||
| 				<img src="{{cover}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> |  | ||||||
| 			<div class="title"> |  | ||||||
| 				{{name}} |  | ||||||
| 			</div> |  | ||||||
| 			<div class="description" *ngIf="description"> |  | ||||||
| 				{{description}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-content colomn_mutiple" *ngIf="seasons.length != 0"> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="title" *ngIf="seasons.length > 1">Seasons:</div> |  | ||||||
| 		<div class="title" *ngIf="seasons.length == 1">Season:</div> |  | ||||||
| 		<div *ngFor="let data of seasons" class="item-list" (click)="onSelectSeason($event, data.id)" (auxclick)="onSelectSeason($event, data.id)"> |  | ||||||
| 			<app-element-season [element]="data"></app-element-season> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-content colomn_mutiple" *ngIf="videos.length != 0"> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="title" *ngIf="videos.length > 1">Videos:</div> |  | ||||||
| 		<div class="title" *ngIf="videos.length == 1">Video:</div> |  | ||||||
| 		<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)"> |  | ||||||
| 			<app-element-video [element]="data"></app-element-video> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="clear"></div> |  | ||||||
| </div> |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| <div class="generic-page"> |  | ||||||
| 	<div class="fill-title colomn_mutiple"> |  | ||||||
| 		<div class="cover-area"> |  | ||||||
| 			<div class="cover" *ngIf="cover != null" > |  | ||||||
| 				<img src="{{cover}}"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div [className]="cover != null ? 'description-area description-area-cover' : 'description-area description-area-no-cover'"> |  | ||||||
| 			<div class="title"> |  | ||||||
| 				{{name}} |  | ||||||
| 			</div> |  | ||||||
| 			<div class="description" *ngIf="description"> |  | ||||||
| 				{{description}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-content colomn_mutiple"> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div *ngFor="let data of series" class="item" (click)="onSelectSeries($event, data.id)" (auxclick)="onSelectSeries($event, data.id)"> |  | ||||||
| 			<app-element-series [element]="data"></app-element-series> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-content colomn_mutiple"> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div *ngFor="let data of videos" class="item item-video" (click)="onSelectVideo($event, data.id)" (auxclick)="onSelectVideo($event, data.id)"> |  | ||||||
| 			<app-element-video [element]="data"></app-element-video> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="clear"></div> |  | ||||||
| </div> |  | ||||||
| @@ -1,216 +0,0 @@ | |||||||
| <div class="generic-page"> |  | ||||||
| 	<div class="title"> |  | ||||||
| 		Upload Media |  | ||||||
| 	</div> |  | ||||||
| 	<div class="clear"><br/></div> |  | ||||||
| 	<div class="request_raw_table"> |  | ||||||
| 		<table> |  | ||||||
| 			<colgroup> |  | ||||||
| 			  <col style="width:10%"> |  | ||||||
| 			  <col style="width:80%"> |  | ||||||
| 			</colgroup>  |  | ||||||
| 			<tbody> |  | ||||||
| 				<tr> |  | ||||||
| 					<td class="left-colomn">format:</td> |  | ||||||
| 					<td class="right-colomn"> |  | ||||||
| 						The format of the media permit to automatic find meta-data:<br/> |  | ||||||
| 						Univers:Series name-sXX-eXX-my name of my media.mkv<br/> |  | ||||||
| 						<b>example:</b> Stargate:SG1-s55-e22-Asgard.mkv <br/> |  | ||||||
| 					</td> |  | ||||||
| 				</tr> |  | ||||||
| 				<tr> |  | ||||||
| 					<td class="left-colomn">Media:</td> |  | ||||||
| 					<td class="right-colomn"> |  | ||||||
| 						<input type="file" |  | ||||||
| 							   (change)="onChangeFile($event.target)" |  | ||||||
| 							   placeholder="Select a media file" |  | ||||||
| 							   accept=".mkv,.webm" |  | ||||||
| 							   width="90%" |  | ||||||
| 							   multiple/> |  | ||||||
| 					</td> |  | ||||||
| 				</tr> |  | ||||||
| 			</tbody> |  | ||||||
| 		</table> |  | ||||||
| 	</div> |  | ||||||
|  |  | ||||||
| 	<div *ngIf="this.parsedElement.length !== 0" class="title"> |  | ||||||
| 		Meta-data: |  | ||||||
| 	</div> |  | ||||||
| 	<div class="clear"><br/></div> |  | ||||||
| 	<div *ngIf="this.parsedElement.length !== 0" class="fill-all"> |  | ||||||
| 		<div class="request_raw_table"> |  | ||||||
| 			<table> |  | ||||||
| 				<colgroup> |  | ||||||
| 				  <col style="width:10%"> |  | ||||||
| 				  <col style="width:70%"> |  | ||||||
| 				  <col style="width:10%"> |  | ||||||
| 				</colgroup>  |  | ||||||
| 				<tbody> |  | ||||||
| 					<tr> |  | ||||||
| 						<td class="left-colomn">Type:</td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							<select [ngModel]="typeId" |  | ||||||
| 								(ngModelChange)="onChangeType($event)" |  | ||||||
| 								[class.error]="typeId === undefined"> |  | ||||||
| 								<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 							</select> |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 					<tr> |  | ||||||
| 						<td class="left-colomn">Series:</td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							<input type="text" |  | ||||||
| 								placeholder="Series of the Media" |  | ||||||
| 								[value]="globalSeries" |  | ||||||
| 								(input)="onSeries($event.target.value)" |  | ||||||
| 								/> |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 					<tr> |  | ||||||
| 						<td class="left-colomn"></td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							<select [ngModel]="seriesId" |  | ||||||
| 									(ngModelChange)="onChangeSeries($event)"> |  | ||||||
| 								<option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 							</select> |  | ||||||
| 						</td> |  | ||||||
| 						<td class="tool-colomn"> |  | ||||||
| 							<!-- |  | ||||||
| 							<button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit"> |  | ||||||
| 								<i class="material-icons">add_circle_outline</i> |  | ||||||
| 							</button> |  | ||||||
| 							--> |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 					<tr> |  | ||||||
| 						<td class="left-colomn">Season:</td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							<input type="number" |  | ||||||
| 								pattern="[0-9]{0-4}" |  | ||||||
| 								placeholder="season of the Media" |  | ||||||
| 								[value]="globalSeason" |  | ||||||
| 								(input)="onSeason($event.target.value)" |  | ||||||
| 								/> |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 				</tbody> |  | ||||||
| 			</table> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw_table"> |  | ||||||
| 			<table> |  | ||||||
| 				<colgroup> |  | ||||||
| 					<col style="width:10%"> |  | ||||||
| 					<col style="width:70%"> |  | ||||||
| 					<col style="width:10%"> |  | ||||||
| 				</colgroup>  |  | ||||||
| 				<thead> |  | ||||||
| 					<tr> |  | ||||||
| 						<th>Episode ID:</th> |  | ||||||
| 						<th>Episode Title:</th> |  | ||||||
| 					</tr> |  | ||||||
| 				</thead> |  | ||||||
| 				<tbody> |  | ||||||
| 					<tr *ngFor="let data of this.parsedElement"> |  | ||||||
| 						<td class="left-colomn"> |  | ||||||
| 							<input type="number" |  | ||||||
| 								pattern="[0-9]{0-4}" |  | ||||||
| 								placeholder="e?" |  | ||||||
| 								[value]="data.episode" |  | ||||||
| 								(input)="onEpisode(data, $event.target.value)" |  | ||||||
| 								[class.error]="data.episodeDetected === true" |  | ||||||
| 							 /> |  | ||||||
| 						</td> |  | ||||||
| 						<td class="right-colomn" > |  | ||||||
| 							<input type="text" |  | ||||||
| 								placeholder="Name of the Media" |  | ||||||
| 								[value]="data.title" |  | ||||||
| 								(input)="onTitle(data, $event.target.value)" |  | ||||||
| 								[class.error]="data.title === ''" |  | ||||||
| 								/> |  | ||||||
| 							<span *ngIf="data.nameDetected === true" class="error"> |  | ||||||
| 								^^^This title already exist !!! |  | ||||||
| 							</span> |  | ||||||
| 						</td> |  | ||||||
| 						<td class="tool-colomn" > |  | ||||||
| 							<button class="button color-button-cancel color-shadow-black" |  | ||||||
| 								(click)="removeElmentFromList(data, $event.target.value)" |  | ||||||
| 								type="submit" |  | ||||||
| 								alt="Delete"> |  | ||||||
| 							<i class="material-icons">delete</i> |  | ||||||
| 						</button> |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 				</tbody> |  | ||||||
| 			</table> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="send_value"> |  | ||||||
| 			<button class="button fill-x color-button-validate color-shadow-black" |  | ||||||
| 			        [disabled]="!needSend" |  | ||||||
| 			        (click)="sendFile()" |  | ||||||
| 			        type="submit"> |  | ||||||
| 				<i class="material-icons">cloud_upload</i> Upload |  | ||||||
| 			</button> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw_table" *ngIf="this.listFileInBdd !== undefined"> |  | ||||||
| 			<table> |  | ||||||
| 				<colgroup> |  | ||||||
| 					<col style="width:10%"> |  | ||||||
| 					<col style="width:70%"> |  | ||||||
| 					<col style="width:10%"> |  | ||||||
| 				</colgroup>  |  | ||||||
| 				<thead> |  | ||||||
| 					<tr> |  | ||||||
| 						<th>Episode ID:</th> |  | ||||||
| 						<th>Episode Title:</th> |  | ||||||
| 					</tr> |  | ||||||
| 				</thead> |  | ||||||
| 				<tbody> |  | ||||||
| 					<tr *ngFor="let data of this.listFileInBdd"> |  | ||||||
| 						<td class="left-colomn" [class.error]="data.episodeDetected === true">{{data.episode}}</td> |  | ||||||
| 						<td class="right-colomn" [class.error]="data.nameDetected === true">{{data.name}}</td> |  | ||||||
| 					</tr> |  | ||||||
| 				</tbody> |  | ||||||
| 			</table> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div *ngIf="this.parsedElement.length !== 0" class="fill-all"> |  | ||||||
| 		<div class="request_raw_table"> |  | ||||||
| 			<table> |  | ||||||
| 				<colgroup> |  | ||||||
| 				  <col style="width:10%"> |  | ||||||
| 				  <col style="width:80%"> |  | ||||||
| 				</colgroup>  |  | ||||||
| 				<tbody> |  | ||||||
| 					<!-- no need |  | ||||||
| 					<tr *ngFor="let data of this.parsedElement"> |  | ||||||
| 						<td class="left-colomn">Keep:</td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							{{data.file.name}} |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 					--> |  | ||||||
| 					<tr *ngFor="let data of this.parsedFailedElement"> |  | ||||||
| 						<td class="left-colomn">Rejected:</td> |  | ||||||
| 						<td class="right-colomn"> |  | ||||||
| 							{{data.file.name}}<br/> ==> {{data.reason}} |  | ||||||
| 						</td> |  | ||||||
| 					</tr> |  | ||||||
| 				</tbody> |  | ||||||
| 			</table> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| <upload-progress [mediaTitle]="upload.labelMediaTitle" |  | ||||||
| 	[mediaUploaded]="upload.mediaSendSize" |  | ||||||
| 	[mediaSize]="upload.mediaSize" |  | ||||||
| 	[result]="upload.result" |  | ||||||
| 	[error]="upload.error"></upload-progress> |  | ||||||
|  |  | ||||||
| <!-- |  | ||||||
| TODO: add a pop-in with: |  | ||||||
|   - upload done |  | ||||||
|   - upload error |  | ||||||
| --> |  | ||||||
| @@ -1,230 +0,0 @@ | |||||||
| <div class="main-reduce edit-page"> |  | ||||||
| 	<div class="title"> |  | ||||||
| 		Edit Media |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsRemoved"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The media has been removed |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsNotFound"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			The media does not exist |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="itemIsLoading"> |  | ||||||
| 		<div class="message-big"> |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 			Loading ...<br/>  |  | ||||||
| 			Please wait. |  | ||||||
| 			<br/><br/><br/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	 |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Title: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="text" |  | ||||||
| 				       placeholder="Name of the Media" |  | ||||||
| 				       [value]="data.name" |  | ||||||
| 				       (input)="onName($event.target.value)" |  | ||||||
| 				       /> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw2"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">description</i> Description: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<textarea (input)="onDescription($event.target.value)" placeholder="Description of the Media" rows=6>{{data.description}}</textarea> |  | ||||||
| 				<!--<input type="text" |  | ||||||
| 				       placeholder="Description of the Media" |  | ||||||
| 				       [value]="data.description" |  | ||||||
| 				       (input)="onDescription($event.target.value)"/>--> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">date_range</i> Date: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="number" |  | ||||||
| 				       pattern="[0-9]{0-4}" |  | ||||||
| 				       placeholder="2112" |  | ||||||
| 				       [value]="data.time" |  | ||||||
| 				       (input)="onDate($event.target)"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Type: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<select [ngModel]="data.typeId" |  | ||||||
| 				        (ngModelChange)="onChangeType($event)"> |  | ||||||
| 					<option *ngFor="let element of listType" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 				</select> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input_add"> |  | ||||||
| 				<button class="button color-button-normal color-shadow-black" (click)="newType()" type="submit"> |  | ||||||
| 					<i class="material-icons">add_circle_outline</i> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Series: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<select [ngModel]="data.seriesId" |  | ||||||
| 				        (ngModelChange)="onChangeSeries($event)"> |  | ||||||
| 					<option *ngFor="let element of listSeries" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 				</select> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input_add"> |  | ||||||
| 				<button class="button color-button-normal color-shadow-black" (click)="newSeries()" type="submit"> |  | ||||||
| 					<i class="material-icons">add_circle_outline</i> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Season: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<select [ngModel]="data.seasonId" |  | ||||||
| 				        (ngModelChange)="onChangeSeason($event)"> |  | ||||||
| 					<option *ngFor="let element of listSeason" [ngValue]="element.value">{{element.label}}</option> |  | ||||||
| 				</select> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input_add"> |  | ||||||
| 				<button class="button color-button-normal color-shadow-black" (click)="newSeason()" type="submit"> |  | ||||||
| 					<i class="material-icons">add_circle_outline</i> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				Episode: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<input type="number" |  | ||||||
| 				       pattern="[0-9]{0-4}" |  | ||||||
| 				       placeholder="5" |  | ||||||
| 				       [value]="data.episode" |  | ||||||
| 				       (input)="onEpisode($event.target)"/> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="send_value"> |  | ||||||
| 			<button class="button fill-x color-button-validate color-shadow-black" [disabled]="!needSend" (click)="sendValues()" type="submit"><i class="material-icons">save_alt</i> Save</button> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- Cover section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Covers |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all"  *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="hide-element"> |  | ||||||
| 			<input type="file"  |  | ||||||
| 	 			   #fileInput |  | ||||||
| 			       (change)="onChangeCover($event.target)" |  | ||||||
| 			       placeholder="Select a cover file" |  | ||||||
| 			       accept=".png,.jpg,.jpeg,.webp"/> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<div class="cover" *ngFor="let element of coversDisplay"> |  | ||||||
| 					<div class="cover-image">  |  | ||||||
| 						<img src="{{element.url}}"/> |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="removeCover(element.id)"> |  | ||||||
| 							<i class="material-icons button-remove">highlight_off</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 				<div class="cover"> |  | ||||||
| 					<div class="cover-no-image">  |  | ||||||
| 					</div> |  | ||||||
| 					<div class="cover-button">  |  | ||||||
| 						<button (click)="fileInput.click()"> |  | ||||||
| 							<i class="material-icons button-add">add_circle_outline</i> |  | ||||||
| 						</button> |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| 	<!-- ------------------------- ADMIN section --------------------------------- --> |  | ||||||
| 	<div class="title" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		Administration |  | ||||||
| 	</div> |  | ||||||
| 	<div class="fill-all" *ngIf="!itemIsRemoved  && !itemIsNotFound && !itemIsLoading"> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">data_usage</i> ID: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				{{data.dataId}} |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 		<div class="request_raw"> |  | ||||||
| 			<div class="label"> |  | ||||||
| 				<i class="material-icons">delete_forever</i> Trash: |  | ||||||
| 			</div> |  | ||||||
| 			<div class="input"> |  | ||||||
| 				<button class="button color-button-cancel color-shadow-black" (click)="removeItem()" type="submit"> |  | ||||||
| 					<i class="material-icons">delete</i> Remove Media |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="clear"></div> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
|  |  | ||||||
| <create-type ></create-type> |  | ||||||
|  |  | ||||||
| <upload-progress [mediaTitle]="upload.labelMediaTitle" |  | ||||||
| 	[mediaUploaded]="upload.mediaSendSize" |  | ||||||
| 	[mediaSize]="upload.mediaSize" |  | ||||||
| 	[result]="upload.result" |  | ||||||
| 	[error]="upload.error"></upload-progress> |  | ||||||
|  |  | ||||||
| <delete-confirm |  | ||||||
| 	[comment]="confirmDeleteComment" |  | ||||||
| 	[imageUrl]=confirmDeleteImageUrl |  | ||||||
|     (callback)="deleteConfirmed()"></delete-confirm> |  | ||||||
|  |  | ||||||
| <app-popin id="popin-new-season" |  | ||||||
|        popTitle="Create a new season" |  | ||||||
|        closeTopRight="true" |  | ||||||
|        closeTitle="Cancel" |  | ||||||
|        validateTitle="Create" |  | ||||||
|        (callback)="eventPopUpSeason($event[0])"> |  | ||||||
|     <p> |  | ||||||
|         Name: <!-- <input type="text" [(ngModel)]="bodyText" /> --> |  | ||||||
|     </p> |  | ||||||
| </app-popin> |  | ||||||
|  |  | ||||||
| <app-popin id="popin-new-series" |  | ||||||
|        popSize="small" |  | ||||||
|        popTitle="Create a new series" |  | ||||||
|        closeTopRight="true" |  | ||||||
|        closeTitle="Cancel" |  | ||||||
|        validateTitle="Create" |  | ||||||
|        (callback)="eventPopUpSeries($event[0])"> |  | ||||||
|     <p> |  | ||||||
|         Name: <!-- <input type="text" [(ngModel)]="bodyText" /> --> |  | ||||||
|     </p> |  | ||||||
| </app-popin> |  | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user