From b94b84ccdb210d3e2662fb41d601e567e235fe0c Mon Sep 17 00:00:00 2001 From: fsossa Date: Tue, 21 Oct 2025 16:22:37 +0200 Subject: [PATCH 01/13] Feat: Update login - add password hash with bcrypt --- backend/studyai_backend/bin/.gitattributes | 2 + backend/studyai_backend/bin/.gitignore | 35 +++ .../bin/.mvn/wrapper/maven-wrapper.properties | 3 + backend/studyai_backend/bin/Dockerfile | 46 +++ .../studyai_backend/bin/docker-compose.yml | 90 ++++++ backend/studyai_backend/bin/mvnw | 295 ++++++++++++++++++ backend/studyai_backend/bin/mvnw.cmd | 189 +++++++++++ backend/studyai_backend/bin/pom.xml | 106 +++++++ .../StudyaiBackendApplication.class | Bin 0 -> 1521 bytes .../config/SecurityConfig.class | Bin 0 -> 1623 bytes .../config/SwaggerConfig.class | Bin 0 -> 1623 bytes .../controller/AuthController.class | Bin 0 -> 3774 bytes .../studyai_backend/dto/LoginRequest.class | Bin 0 -> 2079 bytes .../studyai_backend/dto/SignupRequest.class | Bin 0 -> 2635 bytes .../pdl/studyai_backend/model/Subject.class | Bin 0 -> 3673 bytes .../com/pdl/studyai_backend/model/User.class | Bin 0 -> 3849 bytes .../repository/UserRepository.class | Bin 0 -> 1478 bytes .../studyai_backend/service/UserService.class | Bin 0 -> 3033 bytes .../src/main/resources/application.properties | 15 + .../StudyaiBackendApplicationTests.class | Bin 0 -> 1307 bytes backend/studyai_backend/pom.xml | 4 + .../config/SecurityConfig.java | 15 + .../studyai_backend/config/SwaggerConfig.java | 32 +- .../controller/AuthController.java | 17 +- .../studyai_backend/service/UserService.java | 25 +- 25 files changed, 843 insertions(+), 31 deletions(-) create mode 100644 backend/studyai_backend/bin/.gitattributes create mode 100644 backend/studyai_backend/bin/.gitignore create mode 100644 backend/studyai_backend/bin/.mvn/wrapper/maven-wrapper.properties create mode 100644 backend/studyai_backend/bin/Dockerfile create mode 100644 backend/studyai_backend/bin/docker-compose.yml create mode 100644 backend/studyai_backend/bin/mvnw create mode 100644 backend/studyai_backend/bin/mvnw.cmd create mode 100644 backend/studyai_backend/bin/pom.xml create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/StudyaiBackendApplication.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/controller/AuthController.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/dto/LoginRequest.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/dto/SignupRequest.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/Subject.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/User.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/repository/UserRepository.class create mode 100644 backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/service/UserService.class create mode 100644 backend/studyai_backend/bin/src/main/resources/application.properties create mode 100644 backend/studyai_backend/bin/src/test/java/com/pdl/studyai_backend/StudyaiBackendApplicationTests.class create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java diff --git a/backend/studyai_backend/bin/.gitattributes b/backend/studyai_backend/bin/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/backend/studyai_backend/bin/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/backend/studyai_backend/bin/.gitignore b/backend/studyai_backend/bin/.gitignore new file mode 100644 index 0000000..7ba97c1 --- /dev/null +++ b/backend/studyai_backend/bin/.gitignore @@ -0,0 +1,35 @@ +HELP.md +target/ +.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +.env +.env* +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/backend/studyai_backend/bin/.mvn/wrapper/maven-wrapper.properties b/backend/studyai_backend/bin/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..c0bcafe --- /dev/null +++ b/backend/studyai_backend/bin/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip diff --git a/backend/studyai_backend/bin/Dockerfile b/backend/studyai_backend/bin/Dockerfile new file mode 100644 index 0000000..4b9a5eb --- /dev/null +++ b/backend/studyai_backend/bin/Dockerfile @@ -0,0 +1,46 @@ +# # Multi-stage Dockerfile for a Spring Boot app (Maven) using MongoDB +# # Build stage +# FROM maven:3.8.8-openjdk-17-slim AS build +# WORKDIR /workspace/app + +# # copy only what is needed to leverage Docker layer caching +# COPY pom.xml mvnw ./ +# COPY .mvn .mvn +# RUN chmod +x ./mvnw || true +# RUN mvn -B dependency:go-offline + +# # copy source and build +# COPY src ./src +# RUN mvn -B -DskipTests package + +# # Runtime stage +# FROM eclipse-temurin:17-jre-jammy +# ARG JAR_FILE=/workspace/app/target/*.jar +# COPY --from=build ${JAR_FILE} /app.jar + +# # non-root user +# RUN addgroup --system spring && adduser --system --ingroup spring spring +# USER spring:spring + +# ENV JAVA_OPTS="-Xms256m -Xmx512m" +# # If you want a default mongo URI for local compose setups, uncomment and adjust: +# # ENV SPRING_DATA_MONGODB_URI="mongodb://mongo:27017/pdl" + +# EXPOSE 8080 + +# ENTRYPOINT ["sh","-c","java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar"] + + +# build stage +FROM maven:3.9.4-eclipse-temurin-17 AS build +WORKDIR /app +COPY pom.xml . +COPY src ./src +RUN mvn -B -DskipTests package + +# run stage +FROM eclipse-temurin:17-jre +WORKDIR /app +COPY --from=build /app/target/*.jar app.jar +EXPOSE 8080 +ENTRYPOINT ["java","-jar","/app/app.jar"] diff --git a/backend/studyai_backend/bin/docker-compose.yml b/backend/studyai_backend/bin/docker-compose.yml new file mode 100644 index 0000000..0c9a012 --- /dev/null +++ b/backend/studyai_backend/bin/docker-compose.yml @@ -0,0 +1,90 @@ +# version: '3.8' +services: + mongo: + image: mongo:6.0 + container_name: studyai-mongo + restart: always + environment: + MONGO_INITDB_DATABASE: studyai + ports: + - "27017:27017" + volumes: + - mongo-data:/data/db + app: + build: . + container_name: studyai-backend + depends_on: + - mongo + environment: + - MONGO_URI=mongodb://mongo:27017/studyai + - PORT=8080 + ports: + - "8080:8080" + restart: on-failure + +volumes: + mongo-data: + + +# version: "3.8" + +# services: +# app: +# build: +# context: . +# dockerfile: Dockerfile +# env_file: .env +# environment: +# - NODE_ENV=development +# - DB_HOST=db +# - REDIS_HOST=redis +# ports: +# - "3000:3000" # adjust if your app listens on another port +# volumes: +# - ./:/usr/src/app +# - /usr/src/app/node_modules +# depends_on: +# db: +# condition: service_healthy +# redis: +# condition: service_started +# restart: unless-stopped +# networks: +# - backend +# # default command for a typical Node backend; change to your start command if different +# command: sh -c "npm install && npm run dev" + +# db: +# image: postgres:14 +# env_file: .env +# environment: +# - POSTGRES_USER +# - POSTGRES_PASSWORD +# - POSTGRES_DB +# ports: +# - "5432:5432" +# volumes: +# - db_data:/var/lib/postgresql/data +# healthcheck: +# test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] +# interval: 10s +# timeout: 5s +# retries: 5 +# restart: unless-stopped +# networks: +# - backend + +# redis: +# image: redis:7 +# ports: +# - "6379:6379" +# restart: unless-stopped +# networks: +# - backend + +# volumes: +# db_data: + +# networks: +# backend: +# driver: bridge \ No newline at end of file diff --git a/backend/studyai_backend/bin/mvnw b/backend/studyai_backend/bin/mvnw new file mode 100644 index 0000000..bd8896b --- /dev/null +++ b/backend/studyai_backend/bin/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/backend/studyai_backend/bin/mvnw.cmd b/backend/studyai_backend/bin/mvnw.cmd new file mode 100644 index 0000000..92450f9 --- /dev/null +++ b/backend/studyai_backend/bin/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/backend/studyai_backend/bin/pom.xml b/backend/studyai_backend/bin/pom.xml new file mode 100644 index 0000000..03c2348 --- /dev/null +++ b/backend/studyai_backend/bin/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.5.6 + + + com.pdl + studyai-backend + 0.0.1-SNAPSHOT + studyai-backend + Backend for StudyAI project + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.3.0 + + + org.springframework.boot + spring-boot-starter-security + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/StudyaiBackendApplication.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/StudyaiBackendApplication.class new file mode 100644 index 0000000000000000000000000000000000000000..c4c951e46f3d844d84e454482cb0f3c274736ae5 GIT binary patch literal 1521 zcmc&!&u`N(6n<{IwF!le!Zu(qc{_C+k_#t_K-~mVr4A%oCLs>UP2AQav4ibQ^e;mK z3GVz+i01^f4s|ezNgQJP*)QMw^}YA)`=>7e(1YzdR0upVIto)JWO&R@SQx1^%;F?8 zHjn2_ydAUX9hY%9Eam-D>}6RZB4&k>b*K?oEB;NGoQ5yP$2_tGRv!r|>|+Ae&fXD$ z+JTCB9XtZ9Q{AUpE8T!Aq*{F?H8(0b;W0%QGLaPEG}CIF@YFn{zBih2YUdfJ4j^#G zg3=g`n3T%WF{i&k0@}A!7%F5eH2Raw@oB;}ml0Z+XqBS;KF7D122sL{p%amC^B=7o z6kc3*C^5(AT$CABj!ik;#qWzr?11YUsjy`gn3{>7&5thbX^;@2I$Q5JRNgAV%Ql3+5;7_4G+wv; zkI?*D=(KQkI)L9AuFX;lu0tCo4{pFsym1Kk&mgQXLGTKM3hGv26W0pdg4?(|{5!bc J!>@+ttsf8}+${hA literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..359ae2d933a0fcc923b786220d2dab7ad6aa154d GIT binary patch literal 1623 zcmd5+TTc@~6g~rmwoA2G#2a2l;zN1aeeubv2@p(3iW)%@pU8A}+79l{tTVIK{vv;Z zi6;8)k20RwMQMR}i3#yxXXjkzJNNVT+sDrUunu>sFhihY4UbYLRdmQkEaEzivN(yX z%i}SV2R+7L3l$?@_2nSi6+Ac6jW-Lj3Kas2#k+*5LG-M5D7Ygq|4=IF9ut^tuk914 zZ0cB4p-!NAth;55HZ@ovv-e&qBdktFBBp3QlL>QDE1DVIOGIiP(4f9I6x59~K|Mg| zjfJH#%9&Ey(Vn0`Ktj6hsI*k7SQ_*v8KbB#j8Ggc^o>rDev_jtrXf$5wX`o2Vb9Y_ zEYPrbAjAB!fuO4xd5DP*Pb5Ap6TeDhEiCnsrp)mnb(j$GF2nF9L9mvguVq-I={JyN zyfV$Saa5bZ8L2!+m9nF9Q`Y`;RjJdI6+IBtx6>?P-MOxX^$(xJY2R-94V8U1y{kbo`t(yBNmPJnady$8dBAw7QzJWS<%7 z=_6*v4W%XUsQV9--$85Hbj$>n+H2htL80Eti(EOGifuKLR-zm0eqf6-qZjjCpWRLk zt`T_u2aDi;s0D#wSLcR{C%85+?CGUg%$_gCR7ZEJa0{6y(nFxJBdx^(?%{H?a2IfA z;&KLFeF^MPSCT{AH*ui!N`@fKo zK!SJvD8xA_tYd`%LWqYrvG4Mo@B8lV)8}^|0H6oAYp_6I)95frnUKK&J7htq(jbeH zz}P%GV&eITg)g{_@LY~X91LHvIOcl0*wvs)V7d4$VKNSOM+ZE#1eUgh6!sp0N@ruA zKy_P1yao*d?PK2uS}R?LCaDBZrRGK@hdiPfJrfDDLP?rwHA;ADHmTRxn{aB6GENL*Z>ca;$Vh0sPjZB&G1pv%7-6hciu;#2+9K+Q2{VR{MZ(R$ zj1qAS>@JWYy)5Q*9W(clcmF%y{gU@}8Yyn5%QR&+oKTB|@YflpHw%JN`c6u}py>?A zGGCEqN+Vxt4wJv>p>%u}$d6pgddhXF{Ao?8Rg@JK;5GVbmWWVTYVwS0EE#F6&O@s- zEo-8);pER{#K%H9$Je8PFx*6*b%IBLxJSosGei4>YYk$)y!3@5@7B1P1Q8ZY@;CxJv^^Znq9s z3B37*De&J(fw>P=u0#G12MBU}VmcO0=%hGN+}#@7Bv6}DM4+`Jj6vD;9}Ay0uFePWS;nLIFts1(U*Q4%8c6WX&kcT4PDcXxdv zzpN5S@V!5(>Z~v2Y+}h)L!^TE;Fq;$o}HO}W_I?kzn{MZfDQP;gARe8jgI;$6SDu5 zO;|rtX+MjTzOi|H$i$N&iw?Mq@w>EIB?;I4jogkOydHWmPvCr^n=m=*|2BNeBTL|H zZn)mzdLklDU^#p|8x9C8+!a#Td#Kr~{8`^4F#kZs+=H_OR%WmdwN`o&mWg-&vDDnC zWWr;L)@CAMRwzj`t%eCt%}>e7YzW?9Loj2*8jTe<)WtMqHX2ilq36#s3}hJyNftPg1;v82fSpEHq?yuox{A3K zNljq?tKb3CmNnriUALB%DO-r3yG;|FuE;hwc9yXBCKZX?-Iev4&UJ(bJC zrL1m%-AuDYM8Z;&XIx|EN@H~%S*7We&b@V)g}IFRzK}c)=vHp5qf()USt;a19dOE! zYvU?{-)(P4d&x(tZ4@xR8T!K?N-OMPLm>88BCv8Dt3&0m9<9NB6*r;nh>^^*Bl!l@ z_O3TNQ8l`pn)%+Hi>%84)nUD$A~K+!y)2g_lJ4k&$Q!jjy9 zzp3?zX_j)!bw%9^i@Zj~Wi+;^pe}m{i$FurpHzoT*;@n5iCCvdTPa4A|*Jb<{`QtFN{ zgWacc4>a)LHi4zGi5`4I;9RvTdCi0ZPRVtN5|LrFaxCSC3!&z0YVyRNRzsOwlRq(0$v z8pVOJS#-q2yB-STHj2l~nDuLPjlbFdt@T#}ZLrY+SBUVgczI*E1 zwpz%+69P+HnY1F|>vAZJ=*4_hN@bZ9N*V%QcT?Hth<1RXweFe&!nbhQ3w_+J_nXBI<`R zvZj3zbMr5=L>v=40x9;54LDuK%6)98|64{JQzipbVZJU#~{7N@%R-`rdCmwPm0&b2lJem(a4_@R5D*F ztp7ocGDqOS3@l7R6WRn8J7+b@$x5q>Q?i*QJ+5~cDuoj>6|#7jY2oajn^n6fP_-U) z|4u-ivJJS+hlxPDvvQV99c~baOQ=|x%1a#&axy2Jnn>^UiS{xT_Zep1&d+{?`LFqRi}-Y30RAuI)5SaND{wX6y9U>B=Pbff0m5`4 t!cAz8AygcC&Y=ilrV!!Q1vs<{5pG|A!)yUU1t{{aU?=Y3TE%*ne*pT{PmTZp literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/dto/SignupRequest.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/dto/SignupRequest.class new file mode 100644 index 0000000000000000000000000000000000000000..eb15dae4a6bb069bf8ef8050e02b6f90054e825d GIT binary patch literal 2635 zcmeHJTTc@~6h2!Dy;v<2P!ul%-datzFDAxIOwd3=QqWK&@kyt<(=xC-v&_sQ_{U5% z(RY88@yr&a*o|!sF+TXPvvX$7eDj@iX7<}}-#>i;fF-z}gNy?YwespA<)Xer_i5de zVLkGLx;C+YNcr0q^>&%?>%NioChv$i+F*Mz(0TrG4%hnF_j05?090cn$ zWDZmsC(})%xad4_V16SOhKFob>~qaq0b3G68fv%{+JRzYU7F_zxQnh6jVAxVurn5N zVOx6Oz&Jy)fdje5vhCn(KB8K`m&(T#Pr2ac8TwXhTMlGjNT20k+JW*3lVzo(%EPQP z{_eF7+Ws_o*>trAUDa;@9?^j@-ULhU`BVTGBhQTXYIBc zMgjM@Av%tj!deS$RO}h4NVk~Pnyp(beAec|)(U5^PvgM!db?yT*2d1D7oo!Dq6^#u zSu7kM;graTk%T4(s#vgxdyq?VYX&$Cxm|Ky20(Rh=>Vr8_dBcbhT`PX zRDv?hIWSx8R|ETvE;sNlt;b=DsZENXT`L>Xqrnzc+}cNjS+mViA09RSP_9rX&UKhs z`6*5_)mlHHJP-$hA!Omql8v-{^I&Oz;zPaPe!h_A<71H^Ao#wxzBY%)`}W>>6Chk$!|5 zDF~CP2n#URgOEYgE{8OPsZ@l;5ja#*5pIsaVLBDz)(9MCQW0*Cz+pB8Ap>_XcNw?~ L_wb#?oK}AT$a>&{ literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/Subject.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/Subject.class new file mode 100644 index 0000000000000000000000000000000000000000..9ba4d8589480d31e6ed99d03924ad9c76183c3cb GIT binary patch literal 3673 zcmds3Yi}Dx6us*v@gu=$Lra13n1%ullr_*4AzA@dTO>;^m6|jXpU`-BVo$p}v&_s! z%`Za&3BL2A5NCFs+QussS8jy*VR!c4xqIf^hrQ>ozkmCKi0;r=b*cq)!7b9pbx5D%QvF?sDF+MAxjhH)e z*N7q-QT=-Im08jj}`9QQc3r1K<7F;2Y|c_!gbmTXmdj6zA@S~=weVmc&v=D zIyn+CL&}*<3Urnk4RWddhP9geBf&fo<^e*VXjmr7BJSC}?in zVVO@fSp-z=rJ^sdb zx?rSMy_@4usj~_}F^Ipd+3fa3j4vcCNUQgfzI>e*t|0 zaqwNm>GOO_DKYQ&JXeRpc`1NR3s$w zD%EhU!K%aZYXfVInt1kWYrL-0Mq$5J*z1UE(_aJXKHaBTq&pI0J$NFPmQF{$Lo6_wnrMA)HErVu7|s6zO<65-PY>TtUf f;raq~_`U++9DRoV)hK-aYv{thiE9nsFX+ZU-F5ti literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/User.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/model/User.class new file mode 100644 index 0000000000000000000000000000000000000000..b12becf7639947ae5ed0055f623e2fbf5175cc29 GIT binary patch literal 3849 zcmeHJU2hvj6us*v@kdP3hL!^5W14>1w5&@gASgnLN-J4%TSU`JeX7R0V`tjknPp}+ zkY9!b61?*V_&10%YsYr+hSpMA<)II|<2!Tb%(-*#U7x@H`RxxP+NQ6nR0-(1HBl$! zQgxp4J>H3Q+R5UiV_hEabNQstqh~_Jom9sn={&T;RB0)olZA7_)v$BF|5QXSpo)wG z+UQLe9ylY_@Mb{ge$17VspzUbX=OhV+e&H2oz%((wAAayaH8x$E0Oa z#nRvsl6@=Yh=vVhBJArtB^Ef?6UdNBJ``*dk%vfe_@5Mq zMT$3Btc7Jh(3HDqmpR;r_$5Phvlu9v&=*Zu+|vIej-r)mri~ljsxO9;>zsGYolK6* zQJdk5unu$iUPpNs$)`#i#{Mn8@jdBdsx z<_eDG6&(H*nElGVcCQAVqIa6KMrQ*$)0&qcUK*_T@aegir+r~|IR5RuR?!hp9&sbR zJ)T^0yAq;gtGB2uf*AR_kpZ^Cbl*6}_G>jsbl zjE&#v)Z>k}f2A{j7JJ{t+anU5_we?+;6?A#xngdOKETWY!jfNG5aC1mXa-@*;o}kx zo24Ai)7cq>%7jB1!i7?V%>_7IDn+=k0Ef$^2p1RN&?-f^v;c>8DZ=FiI9x47xUv9; zYo!P+YR_bIS`VL;)Wc_`2-oP-8H8y)lp$=DAe^8OHB_O_q@S+C{u0j$X1D0Zze|59 AHUIzs literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/repository/UserRepository.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/repository/UserRepository.class new file mode 100644 index 0000000000000000000000000000000000000000..65c0f4d0cdb83038dd8887f2cfd1309a268f0176 GIT binary patch literal 1478 zcmcgsOK;RL5FVG(>~5d5lsBy@Pzs0Sz>Ten02NUwr4oHea6w+jyLCzIV0)|XFGB(e z?))Pzh;g#*ZmWp)fH=g;*yHb;`8+c}e}DZB059NC03!sRTf?J_NfjNiLl$wJMR}4& z)^(E}lOJ1*e-bK*jL5Z>PMcn|YlV4tVg@iuV5Yd6GS!K;S_gtV0<~41N+sPIflDio z_Xv!>(uoM5PGEZAy>5&)H5ex&zjl=oR;Py|p%_FiQ|6>rG&j1Hip)Nvjrz{Mpstq- z>H$Je7nXFCGo`enEkTb#Lb~Cov{b4@8jL9I;Za){p*S+Mjn2^i+{LqmhCF4~(zZ;6 z{hus}Kw=+2jw-W`pi7u}i1LSLeE`2J#f~4CvoMGD)xw@f`x;!w|53P6 a?A+|1+=AO^11#e=g(!Dm0VpgX(}O>S*UDo6 literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/service/UserService.class b/backend/studyai_backend/bin/src/main/java/com/pdl/studyai_backend/service/UserService.class new file mode 100644 index 0000000000000000000000000000000000000000..7acd1f65443c291db0eb8ca2870e615274fd207a GIT binary patch literal 3033 zcmcguTW{1j6h1C(GcyddTnY;;tXpm~ToTx2LF^!;?h2$z0VG2bou$>X} zL-;L7yAu1pKMHZ2Oj|lcJE1B(%;Y#e{?7T%E&lJ*-yZ>B8SZ#6Mc}T{QIIkrgV$`p zf=H!77AJwRc|2s|Ri8y~xQqkC^*}^Cc!t7iDSI$YV7@q&Fu4&t>A&WYB`~ddrf?^8 zx=&Fy!YV!N5tzLvq_Fo19P5m4cAw+Hzf{aUI7nb_2lav0N;lvTnK}MUYHn0A;4wuv zGm$VWl%$zf{e-9H587(3ZE|Xd8K(}wcW(KmTQp))DogvEZh`o8#ZqCYkg?F{c{0SU zb*{OL(89V_DX!nrqx!EaTyyfV670kX3~;j#JyW zP+(HNo(to6HB@Sw+; z4{#zT1kP23G2AL-vBh5?yt9-8{e;?_eBk-{X{Vg*!_)SpR_fjL^xi~E+ z7^6m~8@l$vXv~kqFSwqsm+Bwie*_Nkcj&g+PIhI_yllW_0=7oFzC(~(t18zKe~4EN z46bX3(HE@vRuee$G?!MSd_@j~5!k-V?qXA1g|K^@;YhpZ!F9Y+xfpv8V8*s8%Y&Qv z-r;)i8}_M_cIKA{zwf%#l>`a29|>b{{;uKW%D^HJIDnT(oFp&_G$no4C4# zyHogV{R6ERN82CZ@V~g4f+P4pi#p{=fOa9b;20b)-Yvk1N`#XY2n%TYYlKs98tt6H zohkUa!k4oZNT({1egV3Tw78Ard@oroRUn)5Y&9 SK5yf%jd8yQKHPv`;nrvE4V$F^ literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/bin/src/main/resources/application.properties b/backend/studyai_backend/bin/src/main/resources/application.properties new file mode 100644 index 0000000..19f54b0 --- /dev/null +++ b/backend/studyai_backend/bin/src/main/resources/application.properties @@ -0,0 +1,15 @@ +spring.application.name=studyai-backend +# Connexion MongoDB via variable d'environnement MONGO_URI (fallback local) +# spring.data.mongodb.uri=${MONGO_URI:mongodb://localhost:27017/studyai} +spring.data.mongodb.uri=mongodb+srv://fulbsossa16_db_user:LZnOK0DIS75p01TO@cluster0.qu7xkv0.mongodb.net/studyai +spring.data.mongodb.database=studyai +server.port=${PORT:8085} + +# mongodb+srv://fulbsossa16_db_user:LZnOK0DIS75p01TO@cluster0.qu7xkv0.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0 + +# Logging +logging.level.org.springframework=INFO + +# Swagger/OpenAPI configuration +springdoc.api-docs.path=/api-docs +springdoc.swagger-ui.path=/swagger-ui diff --git a/backend/studyai_backend/bin/src/test/java/com/pdl/studyai_backend/StudyaiBackendApplicationTests.class b/backend/studyai_backend/bin/src/test/java/com/pdl/studyai_backend/StudyaiBackendApplicationTests.class new file mode 100644 index 0000000000000000000000000000000000000000..4ed39f2fa363acbd8cea577e0906b4f12d0723b6 GIT binary patch literal 1307 zcmcgsOK;RL5FRh>KEguFLV5KvDwp<>TsW}^X$w@U6hLB2B~Hlec(-m7JJ?Ru{bfiX z!JQw47$-mrEG-Ab!H&l>{^t4R^OyG@0bm5{9cVFl;;cx#bUr!c$2<|HNXjfvoUgJu zS8pa<97&xe<3`?Y#8Fx1N^q}?-lM0k14|56Yk-{VS@L3XD1~RxeyFtaj~HCq+}dZb z^w?yw13d;Sr?yY6HMR?vSg^p!^z%|;0EmOL zxN(MpYi&GEBz^~pao3}AsC1?*#gorTHI-IsK^~^o6ePc`NS9$Oa_$^XRW9BC^pZ(( z90Dk*vV10SgEEh)1Mx2%*ucz4hats+dvSoCDj`ow%IoZF>Si3e8Q1ms6IPRn|(qRUvov zv2u#sj>4?h>>zDB4Y>}xaEs`CK8I=wU04_f(b!a0$Q_~sgL~(bzaBNBfBN$@3;}_N zPrn*~7OiDyliZ=xeY$1zjXps4^&ol&{ZF;c3hluLXsy!TZ>-=N3`hdFPTCgSpi{6~ aqwnu%Hy5Dw7NE7@Hob4boga920losk-i>eo literal 0 HcmV?d00001 diff --git a/backend/studyai_backend/pom.xml b/backend/studyai_backend/pom.xml index 72dd86e..03c2348 100644 --- a/backend/studyai_backend/pom.xml +++ b/backend/studyai_backend/pom.xml @@ -68,6 +68,10 @@ springdoc-openapi-starter-webmvc-ui 2.3.0 + + org.springframework.boot + spring-boot-starter-security + diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java new file mode 100644 index 0000000..3b92765 --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java @@ -0,0 +1,15 @@ +package com.pdl.studyai_backend.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java index c286bac..442222a 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java @@ -1,19 +1,19 @@ -// package com.pdl.studyai_backend.config; +package com.pdl.studyai_backend.config; -// import io.swagger.v3.oas.models.OpenAPI; -// import io.swagger.v3.oas.models.info.Info; -// import org.springframework.context.annotation.Bean; -// import org.springframework.context.annotation.Configuration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; -// @Configuration -// public class SwaggerConfig { +@Configuration +public class SwaggerConfig { -// @Bean -// public OpenAPI studyAIAPI() { -// return new OpenAPI() -// .info(new Info() -// .title("StudyAI API") -// .description("API documentation for StudyAI project") -// .version("1.0.0")); -// } -// } + @Bean + public OpenAPI studyAIAPI() { + return new OpenAPI() + .info(new Info() + .title("StudyAI API") + .description("API documentation for StudyAI project") + .version("1.0.0")); + } +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java index ef3dc77..90f78ed 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java @@ -13,11 +13,17 @@ import com.pdl.studyai_backend.model.User; import com.pdl.studyai_backend.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; + @RestController @RequestMapping("/api/auth") public class AuthController { private final UserService userService; + + @Autowired + private PasswordEncoder passwordEncoder; public AuthController(UserService svc) { this.userService = svc; @@ -28,8 +34,9 @@ public ResponseEntity signup(@Valid @RequestBody SignupRequest req) { if (userService.existsByEmail(req.getEmail())) { return ResponseEntity.badRequest().body(Map.of("error", "Email déjà utilisé")); } - // TODO : hasher le mot de passe (bcrypt) avant save - User u = new User(req.getFullName(), req.getEmail(), req.getPassword()); + // hasher le mot de passe (bcrypt) avant save + User u = new User(req.getFullName(), req.getEmail(), passwordEncoder.encode(req.getPassword())); + userService.create(u); return ResponseEntity.ok(Map.of("message", "Utilisateur créé")); } @@ -38,8 +45,8 @@ public ResponseEntity signup(@Valid @RequestBody SignupRequest req) { public ResponseEntity login(@Valid @RequestBody LoginRequest req) { return userService.findByEmail(req.getEmail()) .map(u -> { - // TODO : remplacer par comparaison bcrypt - if (u.getPassword().equals(req.getPassword())) { + boolean matches = passwordEncoder.matches(req.getPassword(), u.getPassword()); + if (matches) { Map payload = new HashMap<>(); payload.put("id", u.getId()); payload.put("email", u.getEmail()); @@ -47,7 +54,7 @@ public ResponseEntity login(@Valid @RequestBody LoginRequest req) { // TODO : générer JWT ici return ResponseEntity.ok(payload); } else { - return ResponseEntity.status(401).body(Map.of("error", "Credentiels invalides")); + return ResponseEntity.status(401).body(Map.of("error", "Identifiants invalides")); } }) .orElseGet(() -> ResponseEntity.status(401).body(Map.of("error", "Utilisateur introuvable"))); diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java index fc050f8..2eba74e 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java @@ -1,36 +1,41 @@ package com.pdl.studyai_backend.service; - import java.util.List; import java.util.Optional; - import org.springframework.stereotype.Service; - import com.pdl.studyai_backend.model.User; import com.pdl.studyai_backend.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; @Service public class UserService { - private final UserRepository repo; + @Autowired + private final UserRepository userRepository; + + @Autowired + private PasswordEncoder passwordEncoder; - public UserService(UserRepository repo) { - this.repo = repo; + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; } public User create(User user) { - return repo.save(user); + // Hachage du mot de passe avant de le sauvegarder + // user.setPassword(passwordEncoder.encode(user.getPassword())); + return userRepository.save(user); } public Optional findByEmail(String email) { - return repo.findByEmail(email); + return userRepository.findByEmail(email); } public List findAll() { - return repo.findAll(); + return userRepository.findAll(); } public boolean existsByEmail(String email) { - return repo.existsByEmail(email); + return userRepository.existsByEmail(email); } } From 4729eaec7b55e2e2c04d84dda4741e89621419c2 Mon Sep 17 00:00:00 2001 From: fsossa Date: Tue, 21 Oct 2025 16:59:12 +0200 Subject: [PATCH 02/13] resolve package json conflict --- frontend/web/package-lock.json | 13 ------------- frontend/web/package.json | 3 --- 2 files changed, 16 deletions(-) diff --git a/frontend/web/package-lock.json b/frontend/web/package-lock.json index ee6e2ff..73de4b2 100644 --- a/frontend/web/package-lock.json +++ b/frontend/web/package-lock.json @@ -14,10 +14,7 @@ "@react-three/fiber": "^9.4.0", "class-variance-authority": "^0.7.1", "framer-motion": "^12.23.24", -<<<<<<< HEAD "lottie-react": "^2.4.1", -======= ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "lucide-react": "^0.546.0", "next": "15.5.5", "react": "19.1.0", @@ -3704,10 +3701,7 @@ "version": "12.23.24", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", @@ -5107,10 +5101,7 @@ "version": "12.23.23", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", -<<<<<<< HEAD -======= "license": "MIT", ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "dependencies": { "motion-utils": "^12.23.6" } @@ -5118,12 +5109,8 @@ "node_modules/motion-utils": { "version": "12.23.6", "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", -<<<<<<< HEAD - "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==" -======= "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", "license": "MIT" ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 }, "node_modules/ms": { "version": "2.1.3", diff --git a/frontend/web/package.json b/frontend/web/package.json index 4802dae..b437dfa 100644 --- a/frontend/web/package.json +++ b/frontend/web/package.json @@ -15,10 +15,7 @@ "@react-three/fiber": "^9.4.0", "class-variance-authority": "^0.7.1", "framer-motion": "^12.23.24", -<<<<<<< HEAD "lottie-react": "^2.4.1", -========= ->>>>>>>>> Temporary merge branch 2 "lucide-react": "^0.546.0", "next": "15.5.5", "react": "19.1.0", From 49f5094397b08bba1bbfaf59c13a38cc1ad3aef6 Mon Sep 17 00:00:00 2001 From: fsossa Date: Tue, 21 Oct 2025 17:12:57 +0200 Subject: [PATCH 03/13] Feat: remove passwordEncoder from userService --- .../java/com/pdl/studyai_backend/service/UserService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java index 2eba74e..984b4ce 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java @@ -5,7 +5,7 @@ import com.pdl.studyai_backend.model.User; import com.pdl.studyai_backend.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; +// import org.springframework.security.crypto.password.PasswordEncoder; @Service @@ -14,8 +14,8 @@ public class UserService { @Autowired private final UserRepository userRepository; - @Autowired - private PasswordEncoder passwordEncoder; + // @Autowired + // private PasswordEncoder passwordEncoder; public UserService(UserRepository userRepository) { this.userRepository = userRepository; From e881733a2c1e906ef83358c7015dfb9bef2f37d1 Mon Sep 17 00:00:00 2001 From: fsossa Date: Tue, 21 Oct 2025 17:30:24 +0200 Subject: [PATCH 04/13] Feat: add model quiz and resume --- .../com/pdl/studyai_backend/model/Quiz.java | 64 +++++++++++++++++++ .../com/pdl/studyai_backend/model/Resume.java | 35 ++++++++++ 2 files changed, 99 insertions(+) create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java new file mode 100644 index 0000000..b745fda --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java @@ -0,0 +1,64 @@ +package com.pdl.studyai_backend.model; + +import java.util.List; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "quizzes") +public class Quiz { + @Id + private String id; + private String subjectId; + private List questions; + private List answers; + + public Quiz() {} + + // Getters et setters + public String getId() { + return id; + } + + public String getSubjectId() { + return subjectId; + } + + public void setSubjectId(String subjectId) { + this.subjectId = subjectId; + } + + public List getQuestions() { + return questions; + } + + public void setQuestions(List questions) { + this.questions = questions; + } + + public List getAnswers() { + return answers; + } + + public void setAnswers(List answers) { + this.answers = answers; + } + + public Quiz(String subjectId, List questions, List answers) { + this.subjectId = subjectId; + this.questions = questions; + this.answers = answers; + } + + public void addQuestion(String question, String answer) { + this.questions.add(question); + this.answers.add(answer); + } + + public void removeQuestion(String question) { + int index = this.questions.indexOf(question); + if (index != -1) { + this.questions.remove(index); + this.answers.remove(index); + } + } +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java new file mode 100644 index 0000000..d25ef60 --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java @@ -0,0 +1,35 @@ +package com.pdl.studyai_backend.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "resumes") +public class Resume { + @Id + private String id; + private String subjectId; + private String texteResume; + + public Resume() {} + + // Getters et setters + public String getId() { + return id; + } + + public String getSubjectId() { + return subjectId; + } + + public void setSubjectId(String subjectId) { + this.subjectId = subjectId; + } + + public String getTexteResume() { + return texteResume; + } + + public void setTexteResume(String texteResume) { + this.texteResume = texteResume; + } +} From 7636f8938202a4efe5dcd5b2e465cb443a10f05f Mon Sep 17 00:00:00 2001 From: Hyckael Date: Wed, 22 Oct 2025 12:51:40 +0200 Subject: [PATCH 05/13] resume page update --- frontend/web/package-lock.json | 1690 +++-------------- frontend/web/package.json | 3 - .../web/src/app/authentication/layout.tsx | 2 +- .../web/src/app/dashboard/resume/page.tsx | 23 + .../src/app/dashboard/upload-success/page.tsx | 2 +- frontend/web/src/app/page.tsx | 2 +- ...ationRobotAi.tsx => animation-robotAi.tsx} | 0 frontend/web/src/component/ui/chat.tsx | 2 +- .../{OptionButton.tsx => option-button.tsx} | 0 .../src/component/ui/resume-pdf-viewer.tsx | 54 + 10 files changed, 388 insertions(+), 1390 deletions(-) create mode 100644 frontend/web/src/app/dashboard/resume/page.tsx rename frontend/web/src/component/ui/{animationRobotAi.tsx => animation-robotAi.tsx} (100%) rename frontend/web/src/component/ui/{OptionButton.tsx => option-button.tsx} (100%) create mode 100644 frontend/web/src/component/ui/resume-pdf-viewer.tsx diff --git a/frontend/web/package-lock.json b/frontend/web/package-lock.json index ee6e2ff..bec9aa3 100644 --- a/frontend/web/package-lock.json +++ b/frontend/web/package-lock.json @@ -14,10 +14,7 @@ "@react-three/fiber": "^9.4.0", "class-variance-authority": "^0.7.1", "framer-motion": "^12.23.24", -<<<<<<< HEAD "lottie-react": "^2.4.1", -======= ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "lucide-react": "^0.546.0", "next": "15.5.5", "react": "19.1.0", @@ -302,405 +299,6 @@ "node": ">=18" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", - "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", - "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", - "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", - "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", - "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", - "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", - "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", - "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", - "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", - "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", - "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", - "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", - "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", - "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", - "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", - "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.3" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", - "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.5.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", - "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", - "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-win32-x64": { "version": "0.34.4", "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", @@ -777,167 +375,55 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mediapipe/tasks-vision": { - "version": "0.10.17", - "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", - "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==" - }, - "node_modules/@monogrid/gainmap-js": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz", - "integrity": "sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw==", - "dependencies": { - "promise-worker-transferable": "^1.0.4" - }, - "peerDependencies": { - "three": ">= 0.159.0" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.5.tgz", - "integrity": "sha512-2Zhvss36s/yL+YSxD5ZL5dz5pI6ki1OLxYlh6O77VJ68sBnlUrl5YqhBgCy7FkdMsp9RBeGFwpuDCdpJOqdKeQ==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.5.tgz", - "integrity": "sha512-FMzm412l9oFB8zdRD+K6HQ1VzlS+sNNsdg0MfvTg0i8lfCyTgP/RFxiu/pGJqZ/IQnzn9xSiLkjOVI7Iv4nbdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "3.3.1" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.5.tgz", - "integrity": "sha512-lYExGHuFIHeOxf40mRLWoA84iY2sLELB23BV5FIDHhdJkN1LpRTPc1MDOawgTo5ifbM5dvAwnGuHyNm60G1+jw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.5.tgz", - "integrity": "sha512-cacs/WQqa96IhqUm+7CY+z/0j9sW6X80KE07v3IAJuv+z0UNvJtKSlT/T1w1SpaQRa9l0wCYYZlRZUhUOvEVmg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.5.tgz", - "integrity": "sha512-tLd90SvkRFik6LSfuYjcJEmwqcNEnVYVOyKTacSazya/SLlSwy/VYKsDE4GIzOBd+h3gW+FXqShc2XBavccHCg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.5.tgz", - "integrity": "sha512-ekV76G2R/l3nkvylkfy9jBSYHeB4QcJ7LdDseT6INnn1p51bmDS1eGoSoq+RxfQ7B1wt+Qa0pIl5aqcx0GLpbw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", + "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==" + }, + "node_modules/@monogrid/gainmap-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz", + "integrity": "sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw==", + "dependencies": { + "promise-worker-transferable": "^1.0.4" + }, + "peerDependencies": { + "three": ">= 0.159.0" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.5.tgz", - "integrity": "sha512-tI+sBu+3FmWtqlqD4xKJcj3KJtqbniLombKTE7/UWyyoHmOyAo3aZ7QcEHIOgInXOG1nt0rwh0KGmNbvSB0Djg==", - "cpu": [ - "x64" - ], + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@next/swc-linux-x64-musl": { + "node_modules/@next/env": { "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.5.tgz", - "integrity": "sha512-kDRh+epN/ulroNJLr+toDjN+/JClY5L+OAWjOrrKCI0qcKvTw9GBx7CU/rdA2bgi4WpZN3l0rf/3+b8rduEwrQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.5.tgz", + "integrity": "sha512-2Zhvss36s/yL+YSxD5ZL5dz5pI6ki1OLxYlh6O77VJ68sBnlUrl5YqhBgCy7FkdMsp9RBeGFwpuDCdpJOqdKeQ==", + "license": "MIT" }, - "node_modules/@next/swc-win32-arm64-msvc": { + "node_modules/@next/eslint-plugin-next": { "version": "15.5.5", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.5.tgz", - "integrity": "sha512-GDgdNPFFqiKjTrmfw01sMMRWhVN5wOCmFzPloxa7ksDfX6TZt62tAK986f0ZYqWpvDFqeBCLAzmgTURvtQBdgw==", - "cpu": [ - "arm64" - ], + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.5.tgz", + "integrity": "sha512-FMzm412l9oFB8zdRD+K6HQ1VzlS+sNNsdg0MfvTg0i8lfCyTgP/RFxiu/pGJqZ/IQnzn9xSiLkjOVI7Iv4nbdQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "fast-glob": "3.3.1" } }, "node_modules/@next/swc-win32-x64-msvc": { @@ -1211,237 +697,37 @@ "jiti": "^2.6.0", "lightningcss": "1.30.1", "magic-string": "^0.30.19", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.14" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz", - "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.5.1" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.14", - "@tailwindcss/oxide-darwin-arm64": "4.1.14", - "@tailwindcss/oxide-darwin-x64": "4.1.14", - "@tailwindcss/oxide-freebsd-x64": "4.1.14", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", - "@tailwindcss/oxide-linux-x64-musl": "4.1.14", - "@tailwindcss/oxide-wasm32-wasi": "4.1.14", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz", - "integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz", - "integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz", - "integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz", - "integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz", - "integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz", - "integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz", - "integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz", - "integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz", - "integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz", - "integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.5", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.0.0" + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.14" } }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "node_modules/@tailwindcss/oxide": { "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz", - "integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==", - "cpu": [ - "arm64" - ], + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz", + "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.5.1" + }, "engines": { "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.14", + "@tailwindcss/oxide-darwin-arm64": "4.1.14", + "@tailwindcss/oxide-darwin-x64": "4.1.14", + "@tailwindcss/oxide-freebsd-x64": "4.1.14", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", + "@tailwindcss/oxide-linux-x64-musl": "4.1.14", + "@tailwindcss/oxide-wasm32-wasi": "4.1.14", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { @@ -1537,7 +823,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1548,7 +833,6 @@ "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -1631,7 +915,6 @@ "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", @@ -1786,348 +1069,93 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz", - "integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.46.1", - "@typescript-eslint/types": "8.46.1", - "@typescript-eslint/typescript-estree": "8.46.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz", - "integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.46.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", - "optional": true, + "license": "ISC", "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], + "node_modules/@typescript-eslint/utils": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz", + "integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.1", + "@typescript-eslint/types": "8.46.1", + "@typescript-eslint/typescript-estree": "8.46.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz", + "integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@typescript-eslint/types": "8.46.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { "version": "1.11.1", @@ -2170,7 +1198,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3132,7 +2159,6 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3307,7 +2333,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -3704,10 +2729,6 @@ "version": "12.23.24", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", @@ -4619,293 +3640,104 @@ "minimist": "^1.2.0" }, "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "json5": "lib/cli.js" } }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=4.0" } }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" } }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "CC0-1.0" }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=0.10" } }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" } }, - "node_modules/lightningcss-win32-arm64-msvc": { + "node_modules/lightningcss": { "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "dev": true, "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "detect-libc": "^2.0.3" + }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" } }, "node_modules/lightningcss-win32-x64-msvc": { @@ -5107,10 +3939,6 @@ "version": "12.23.23", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", -<<<<<<< HEAD -======= - "license": "MIT", ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "dependencies": { "motion-utils": "^12.23.6" } @@ -5118,12 +3946,7 @@ "node_modules/motion-utils": { "version": "12.23.6", "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", -<<<<<<< HEAD "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==" -======= - "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", - "license": "MIT" ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 }, "node_modules/ms": { "version": "2.1.3", @@ -5613,7 +4436,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5623,7 +4445,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -6437,7 +5258,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6649,7 +5469,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6919,6 +5738,111 @@ "optional": true } } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.5.tgz", + "integrity": "sha512-lYExGHuFIHeOxf40mRLWoA84iY2sLELB23BV5FIDHhdJkN1LpRTPc1MDOawgTo5ifbM5dvAwnGuHyNm60G1+jw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.5.tgz", + "integrity": "sha512-cacs/WQqa96IhqUm+7CY+z/0j9sW6X80KE07v3IAJuv+z0UNvJtKSlT/T1w1SpaQRa9l0wCYYZlRZUhUOvEVmg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.5.tgz", + "integrity": "sha512-tLd90SvkRFik6LSfuYjcJEmwqcNEnVYVOyKTacSazya/SLlSwy/VYKsDE4GIzOBd+h3gW+FXqShc2XBavccHCg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.5.tgz", + "integrity": "sha512-ekV76G2R/l3nkvylkfy9jBSYHeB4QcJ7LdDseT6INnn1p51bmDS1eGoSoq+RxfQ7B1wt+Qa0pIl5aqcx0GLpbw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.5.tgz", + "integrity": "sha512-tI+sBu+3FmWtqlqD4xKJcj3KJtqbniLombKTE7/UWyyoHmOyAo3aZ7QcEHIOgInXOG1nt0rwh0KGmNbvSB0Djg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.5.tgz", + "integrity": "sha512-kDRh+epN/ulroNJLr+toDjN+/JClY5L+OAWjOrrKCI0qcKvTw9GBx7CU/rdA2bgi4WpZN3l0rf/3+b8rduEwrQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.5.tgz", + "integrity": "sha512-GDgdNPFFqiKjTrmfw01sMMRWhVN5wOCmFzPloxa7ksDfX6TZt62tAK986f0ZYqWpvDFqeBCLAzmgTURvtQBdgw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/frontend/web/package.json b/frontend/web/package.json index e6ac277..b437dfa 100644 --- a/frontend/web/package.json +++ b/frontend/web/package.json @@ -15,10 +15,7 @@ "@react-three/fiber": "^9.4.0", "class-variance-authority": "^0.7.1", "framer-motion": "^12.23.24", -<<<<<<< HEAD "lottie-react": "^2.4.1", -======= ->>>>>>> bbb2133e48bc0a31aa155dbe8a934ecb9b9df615 "lucide-react": "^0.546.0", "next": "15.5.5", "react": "19.1.0", diff --git a/frontend/web/src/app/authentication/layout.tsx b/frontend/web/src/app/authentication/layout.tsx index 835dcba..bfb7455 100644 --- a/frontend/web/src/app/authentication/layout.tsx +++ b/frontend/web/src/app/authentication/layout.tsx @@ -1,7 +1,7 @@ 'use client'; import Image from 'next/image'; -import { Animation } from "@/component/ui/animationRobotAi"; +import { Animation } from "@/component/ui/animation-robotAi"; export default function AuthLayout({ children }: { children: React.ReactNode }) { return (
diff --git a/frontend/web/src/app/dashboard/resume/page.tsx b/frontend/web/src/app/dashboard/resume/page.tsx new file mode 100644 index 0000000..b524f28 --- /dev/null +++ b/frontend/web/src/app/dashboard/resume/page.tsx @@ -0,0 +1,23 @@ +import { ResumePDFViewer } from "../../../component/ui/resume-pdf-viewer"; +import { ArrowLeft } from "lucide-react"; + +export default function App() { + return ( +
+ {/* Back arrow and title */} +
+ +

+ Votre Résumé +

+
+ + {/* PDF viewer section */} +
+ +
+
+ ); +} \ No newline at end of file diff --git a/frontend/web/src/app/dashboard/upload-success/page.tsx b/frontend/web/src/app/dashboard/upload-success/page.tsx index ead0213..39e353e 100644 --- a/frontend/web/src/app/dashboard/upload-success/page.tsx +++ b/frontend/web/src/app/dashboard/upload-success/page.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { FileText, Pencil, MessageCircle, ClipboardList } from 'lucide-react'; -import OptionButton from "../../../component/ui/OptionButton"; +import OptionButton from "../../../component/ui/option-button"; export default function UploadSuccess() { const [uploadedFile, setUploadedFile] = useState(null); diff --git a/frontend/web/src/app/page.tsx b/frontend/web/src/app/page.tsx index 7466ace..19afb97 100644 --- a/frontend/web/src/app/page.tsx +++ b/frontend/web/src/app/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Animation } from "@/component/ui/animationRobotAi"; +import { Animation } from "@/component/ui/animation-robotAi"; import { Button } from '@/component/ui/button'; import { useRouter } from 'next/navigation'; diff --git a/frontend/web/src/component/ui/animationRobotAi.tsx b/frontend/web/src/component/ui/animation-robotAi.tsx similarity index 100% rename from frontend/web/src/component/ui/animationRobotAi.tsx rename to frontend/web/src/component/ui/animation-robotAi.tsx diff --git a/frontend/web/src/component/ui/chat.tsx b/frontend/web/src/component/ui/chat.tsx index 9d1a938..a10afb4 100644 --- a/frontend/web/src/component/ui/chat.tsx +++ b/frontend/web/src/component/ui/chat.tsx @@ -64,7 +64,7 @@ const AIMessageBar = () => {

How can I help you today?

- Ask me anything and I'll do my best to assist you! + Ask me anything and I'll do my best to assist you!

) : ( diff --git a/frontend/web/src/component/ui/OptionButton.tsx b/frontend/web/src/component/ui/option-button.tsx similarity index 100% rename from frontend/web/src/component/ui/OptionButton.tsx rename to frontend/web/src/component/ui/option-button.tsx diff --git a/frontend/web/src/component/ui/resume-pdf-viewer.tsx b/frontend/web/src/component/ui/resume-pdf-viewer.tsx new file mode 100644 index 0000000..a9d85ea --- /dev/null +++ b/frontend/web/src/component/ui/resume-pdf-viewer.tsx @@ -0,0 +1,54 @@ +import { Card } from "./card"; + +export function ResumePDFViewer() { + return ( +
+ +
+

Adobe Acrobat PDF Files

+ +
+

+ Adobe® Portable Document Format (PDF) is a universal file format that preserves all + of the fonts, formatting, colours and graphics of any source document, regardless of + the application and platform used to create it. +

+ +

+ Adobe PDF is an ideal format for electronic document distribution as it overcomes the + problems commonly encountered with electronic file sharing. +

+ +
    +
  • + Anyone, anywhere can open a PDF file. All you need is the free Adobe Acrobat + Reader. Recipients of other file formats sometimes can't open files because they + don't have the applications used to create the documents. +
  • + +
  • + PDF files always print correctly on any printing device. +
  • + +
  • + PDF files always display exactly as created, regardless of fonts, software, and + operating systems. Fonts, and graphics are not lost due to platform, software, and + version incompatibilities. +
  • + +
  • + The free Acrobat Reader is easy to download and can be freely distributed by + anyone. +
  • + +
  • + Compact PDF files are smaller than their source files and download a + page at a time for fast display on the Web. +
  • +
+
+
+
+
+ ); +} \ No newline at end of file From 5d7373cb4044e0fdce6b1f87e6ff8cd54e9dca9b Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Wed, 22 Oct 2025 14:18:51 +0200 Subject: [PATCH 06/13] quizz, resume, subject, user --- backend/studyai_backend/.gitignore | 2 + .../controller/AuthController.java | 36 +++++++++--------- .../controller/ResumeController.java | 33 +++++++++++++++++ .../studyai_backend/dto/ResumeRequest.java | 23 ++++++++++++ .../com/pdl/studyai_backend/model/Quiz.java | 1 - .../com/pdl/studyai_backend/model/Resume.java | 10 ++++- .../com/pdl/studyai_backend/model/User.java | 8 ---- .../repository/ResumeRepository.java | 9 +++++ .../service/ResumeService.java | 37 +++++++++++++++++++ 9 files changed, 130 insertions(+), 29 deletions(-) create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/ResumeController.java create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/dto/ResumeRequest.java create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/repository/ResumeRepository.java create mode 100644 backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/ResumeService.java diff --git a/backend/studyai_backend/.gitignore b/backend/studyai_backend/.gitignore index 191ba70..5628a9d 100644 --- a/backend/studyai_backend/.gitignore +++ b/backend/studyai_backend/.gitignore @@ -1,5 +1,7 @@ HELP.md + target/ +target/* .mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java index 90f78ed..9e13f5b 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java @@ -41,22 +41,22 @@ public ResponseEntity signup(@Valid @RequestBody SignupRequest req) { return ResponseEntity.ok(Map.of("message", "Utilisateur créé")); } - @PostMapping("/login") - public ResponseEntity login(@Valid @RequestBody LoginRequest req) { - return userService.findByEmail(req.getEmail()) - .map(u -> { - boolean matches = passwordEncoder.matches(req.getPassword(), u.getPassword()); - if (matches) { - Map payload = new HashMap<>(); - payload.put("id", u.getId()); - payload.put("email", u.getEmail()); - payload.put("fullName", u.getFullName()); - // TODO : générer JWT ici - return ResponseEntity.ok(payload); - } else { - return ResponseEntity.status(401).body(Map.of("error", "Identifiants invalides")); - } - }) - .orElseGet(() -> ResponseEntity.status(401).body(Map.of("error", "Utilisateur introuvable"))); - } + // @PostMapping("/login") + // public ResponseEntity login(@Valid @RequestBody LoginRequest req) { + // return userService.findByEmail(req.getEmail()) + // .map(u -> { + // boolean matches = passwordEncoder.matches(req.getPassword(), u.getPassword()); + // if (matches) { + // Map payload = new HashMap<>(); + // payload.put("id", u.getId()); + // payload.put("email", u.getEmail()); + // payload.put("fullName", u.getFullName()); + // // TODO : générer JWT ici + // return ResponseEntity.ok(payload); + // } else { + // return ResponseEntity.status(401).body(Map.of("error", "Identifiants invalides")); + // } + // }) + // .orElseGet(() -> ResponseEntity.status(401).body(Map.of("error", "Utilisateur introuvable"))); + // } } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/ResumeController.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/ResumeController.java new file mode 100644 index 0000000..bd80c75 --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/ResumeController.java @@ -0,0 +1,33 @@ +package com.pdl.studyai_backend.controller; + +import java.util.HashMap; +import java.util.Map; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import com.pdl.studyai_backend.dto.ResumeRequest; +import com.pdl.studyai_backend.model.Resume; +import com.pdl.studyai_backend.service.ResumeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@RestController +@RequestMapping("api/resume") +public class ResumeController { + private ResumeService resumeService; + + public ResumeController(ResumeService service) { + this.resumeService = service; + } + + @PostMapping("/create") + public ResponseEntity createResume(@RequestBody ResumeRequest reqResume) { + + Resume r = new Resume(reqResume.getSubjectId(), reqResume.getTextResume()); + resumeService.create(r); + + return ResponseEntity.ok(Map.of("message", "Résumé créé avec succès !")); + } + +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/dto/ResumeRequest.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/dto/ResumeRequest.java new file mode 100644 index 0000000..0b46bfc --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/dto/ResumeRequest.java @@ -0,0 +1,23 @@ +package com.pdl.studyai_backend.dto; + +import jakarta.validation.constraints.NotBlank;; + +public class ResumeRequest { + @NotBlank + private String subjectId; + + @NotBlank + private String texteResume; + + public String getSubjectId() { + return subjectId; + } + + public String getTextResume() { + return texteResume; + } + + public void setTextResume(String textResume) { + this.texteResume = textResume; + } +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java index b745fda..34dbad6 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Quiz.java @@ -14,7 +14,6 @@ public class Quiz { public Quiz() {} - // Getters et setters public String getId() { return id; } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java index d25ef60..6528fe6 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/Resume.java @@ -4,15 +4,21 @@ import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "resumes") + public class Resume { @Id private String id; private String subjectId; private String texteResume; - public Resume() {} + public Resume() { + } + + public Resume(String subjectId, String texteResume) { + this.subjectId = subjectId; + this.texteResume = texteResume; + } - // Getters et setters public String getId() { return id; } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/User.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/User.java index 5e2595b..f9aa758 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/User.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/model/User.java @@ -1,8 +1,6 @@ package com.pdl.studyai_backend.model; import java.time.Instant; -import java.util.ArrayList; -import java.util.List; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @@ -18,7 +16,6 @@ public class User { private String fullName; private String email; private String password; // pour l'instant stocké en clair — à remplacer par hash (bcrypt) - // private List roles = new ArrayList<>(); private Instant createdAt = Instant.now(); public User() {} @@ -27,10 +24,8 @@ public User(String fullName, String email, String password) { this.fullName = fullName; this.email = email; this.password = password; - // this.roles.add("USER"); } - // getters & setters (ou utilise Lombok @Data) public String getId() { return id; } public void setId(String id) { this.id = id; } @@ -43,9 +38,6 @@ public User(String fullName, String email, String password) { public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } - // public List getRoles() { return roles; } - // public void setRoles(List roles) { this.roles = roles; } - public Instant getCreatedAt() { return createdAt; } public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/repository/ResumeRepository.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/repository/ResumeRepository.java new file mode 100644 index 0000000..f1b4328 --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/repository/ResumeRepository.java @@ -0,0 +1,9 @@ +package com.pdl.studyai_backend.repository; +import org.springframework.data.mongodb.repository.MongoRepository; +import com.pdl.studyai_backend.model.Resume; + +public interface ResumeRepository extends MongoRepository { + // Optional findByOptional(String idResume); + + // boolean existsByIdResume(String idResume); +} diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/ResumeService.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/ResumeService.java new file mode 100644 index 0000000..91c8703 --- /dev/null +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/ResumeService.java @@ -0,0 +1,37 @@ +package com.pdl.studyai_backend.service; +import java.util.List; +import java.util.Optional; +import org.springframework.stereotype.Service; +import com.pdl.studyai_backend.model.Resume; +import com.pdl.studyai_backend.repository.ResumeRepository; +import org.springframework.beans.factory.annotation.Autowired; + +@Service +public class ResumeService { + + @Autowired + private ResumeRepository resumeRepository; + + // @Autowired + // private PasswordEncoder passwordEncoder; + + // public ResumeRepository(ResumeRepository resumeRepository) { + // this.resumeRepository = resumeRepository; + // } + + public Resume create(Resume resume) { + return resumeRepository.save(resume); + } + + // public Optional findByEmail(String email) { + // return ResumeRepository.findByEmail(email); + // } + + public List findAll() { + return resumeRepository.findAll(); + } + + // public boolean existsByEmail(String email) { + // return resumeRepository.existsByEmail(email); + // } +} From 252e808bf81df3231f427815203dbc35bc4e6fc1 Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Wed, 22 Oct 2025 14:21:49 +0200 Subject: [PATCH 07/13] fix: .gitignore change --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 48023b1..84d69c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ +/frontend/web/package-lock.json +/backend/*.class -.class \ No newline at end of file + +# /backend/studyai_backend/src/main/java/com/ \ No newline at end of file From 2bd050203f2cb3c13dfc92fdfc6100f3c599bf48 Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Wed, 22 Oct 2025 14:56:01 +0200 Subject: [PATCH 08/13] fix: bcrypt solution ok --- backend/studyai_backend/pom.xml | 2 +- .../studyai_backend/config/SwaggerConfig.java | 32 ++++++------- .../controller/AuthController.java | 47 ++++++++----------- .../studyai_backend/service/UserService.java | 26 ++++------ 4 files changed, 47 insertions(+), 60 deletions(-) diff --git a/backend/studyai_backend/pom.xml b/backend/studyai_backend/pom.xml index 03c2348..155c2ae 100644 --- a/backend/studyai_backend/pom.xml +++ b/backend/studyai_backend/pom.xml @@ -103,4 +103,4 @@
- + \ No newline at end of file diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java index 442222a..c286bac 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java @@ -1,19 +1,19 @@ -package com.pdl.studyai_backend.config; +// package com.pdl.studyai_backend.config; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +// import io.swagger.v3.oas.models.OpenAPI; +// import io.swagger.v3.oas.models.info.Info; +// import org.springframework.context.annotation.Bean; +// import org.springframework.context.annotation.Configuration; -@Configuration -public class SwaggerConfig { +// @Configuration +// public class SwaggerConfig { - @Bean - public OpenAPI studyAIAPI() { - return new OpenAPI() - .info(new Info() - .title("StudyAI API") - .description("API documentation for StudyAI project") - .version("1.0.0")); - } -} +// @Bean +// public OpenAPI studyAIAPI() { +// return new OpenAPI() +// .info(new Info() +// .title("StudyAI API") +// .description("API documentation for StudyAI project") +// .version("1.0.0")); +// } +// } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java index 9e13f5b..ef3dc77 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/controller/AuthController.java @@ -13,17 +13,11 @@ import com.pdl.studyai_backend.model.User; import com.pdl.studyai_backend.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; - @RestController @RequestMapping("/api/auth") public class AuthController { private final UserService userService; - - @Autowired - private PasswordEncoder passwordEncoder; public AuthController(UserService svc) { this.userService = svc; @@ -34,29 +28,28 @@ public ResponseEntity signup(@Valid @RequestBody SignupRequest req) { if (userService.existsByEmail(req.getEmail())) { return ResponseEntity.badRequest().body(Map.of("error", "Email déjà utilisé")); } - // hasher le mot de passe (bcrypt) avant save - User u = new User(req.getFullName(), req.getEmail(), passwordEncoder.encode(req.getPassword())); - + // TODO : hasher le mot de passe (bcrypt) avant save + User u = new User(req.getFullName(), req.getEmail(), req.getPassword()); userService.create(u); return ResponseEntity.ok(Map.of("message", "Utilisateur créé")); } - // @PostMapping("/login") - // public ResponseEntity login(@Valid @RequestBody LoginRequest req) { - // return userService.findByEmail(req.getEmail()) - // .map(u -> { - // boolean matches = passwordEncoder.matches(req.getPassword(), u.getPassword()); - // if (matches) { - // Map payload = new HashMap<>(); - // payload.put("id", u.getId()); - // payload.put("email", u.getEmail()); - // payload.put("fullName", u.getFullName()); - // // TODO : générer JWT ici - // return ResponseEntity.ok(payload); - // } else { - // return ResponseEntity.status(401).body(Map.of("error", "Identifiants invalides")); - // } - // }) - // .orElseGet(() -> ResponseEntity.status(401).body(Map.of("error", "Utilisateur introuvable"))); - // } + @PostMapping("/login") + public ResponseEntity login(@Valid @RequestBody LoginRequest req) { + return userService.findByEmail(req.getEmail()) + .map(u -> { + // TODO : remplacer par comparaison bcrypt + if (u.getPassword().equals(req.getPassword())) { + Map payload = new HashMap<>(); + payload.put("id", u.getId()); + payload.put("email", u.getEmail()); + payload.put("fullName", u.getFullName()); + // TODO : générer JWT ici + return ResponseEntity.ok(payload); + } else { + return ResponseEntity.status(401).body(Map.of("error", "Credentiels invalides")); + } + }) + .orElseGet(() -> ResponseEntity.status(401).body(Map.of("error", "Utilisateur introuvable"))); + } } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java index 984b4ce..c76a28a 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/service/UserService.java @@ -1,41 +1,35 @@ package com.pdl.studyai_backend.service; + import java.util.List; import java.util.Optional; + import org.springframework.stereotype.Service; + import com.pdl.studyai_backend.model.User; import com.pdl.studyai_backend.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -// import org.springframework.security.crypto.password.PasswordEncoder; - @Service public class UserService { - @Autowired - private final UserRepository userRepository; - - // @Autowired - // private PasswordEncoder passwordEncoder; + private final UserRepository repo; - public UserService(UserRepository userRepository) { - this.userRepository = userRepository; + public UserService(UserRepository repo) { + this.repo = repo; } public User create(User user) { - // Hachage du mot de passe avant de le sauvegarder - // user.setPassword(passwordEncoder.encode(user.getPassword())); - return userRepository.save(user); + return repo.save(user); } public Optional findByEmail(String email) { - return userRepository.findByEmail(email); + return repo.findByEmail(email); } public List findAll() { - return userRepository.findAll(); + return repo.findAll(); } public boolean existsByEmail(String email) { - return userRepository.existsByEmail(email); + return repo.existsByEmail(email); } } From 33343022037b86cb5680fc5422b50c96f68021b0 Mon Sep 17 00:00:00 2001 From: fsossa Date: Wed, 22 Oct 2025 15:07:00 +0200 Subject: [PATCH 09/13] Feat: fix spring security and set admin param --- .../studyai_backend/src/main/resources/application.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/studyai_backend/src/main/resources/application.properties b/backend/studyai_backend/src/main/resources/application.properties index 19f54b0..3b8b97b 100644 --- a/backend/studyai_backend/src/main/resources/application.properties +++ b/backend/studyai_backend/src/main/resources/application.properties @@ -13,3 +13,6 @@ logging.level.org.springframework=INFO # Swagger/OpenAPI configuration springdoc.api-docs.path=/api-docs springdoc.swagger-ui.path=/swagger-ui + +spring.security.user.name=admin +spring.security.user.password=$2a$12$/4GJAlGVFvPCsXvqVQxYhegITJTsIhdfFRi7gRT9y4qXU/uAXtQGC From cbd885837ca9c1b511329b0453af759f0c91f5d9 Mon Sep 17 00:00:00 2001 From: fsossa Date: Wed, 22 Oct 2025 16:48:57 +0200 Subject: [PATCH 10/13] Feat: Fix api authentication by springsecurity. set csrf disabled --- .../config/SecurityConfig.java | 16 ++++++++++ .../studyai_backend/config/SwaggerConfig.java | 32 +++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java index 3b92765..a9f1cde 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SecurityConfig.java @@ -2,8 +2,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @@ -12,4 +14,18 @@ public class SecurityConfig { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()); + // .authorizeHttpRequests(auth -> auth + // .requestMatchers( + // "/signup", "/login", + // "/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**" + // ).permitAll() + // .anyRequest().authenticated() + // ); + return http.build(); + } } diff --git a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java index c286bac..442222a 100644 --- a/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java +++ b/backend/studyai_backend/src/main/java/com/pdl/studyai_backend/config/SwaggerConfig.java @@ -1,19 +1,19 @@ -// package com.pdl.studyai_backend.config; +package com.pdl.studyai_backend.config; -// import io.swagger.v3.oas.models.OpenAPI; -// import io.swagger.v3.oas.models.info.Info; -// import org.springframework.context.annotation.Bean; -// import org.springframework.context.annotation.Configuration; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; -// @Configuration -// public class SwaggerConfig { +@Configuration +public class SwaggerConfig { -// @Bean -// public OpenAPI studyAIAPI() { -// return new OpenAPI() -// .info(new Info() -// .title("StudyAI API") -// .description("API documentation for StudyAI project") -// .version("1.0.0")); -// } -// } + @Bean + public OpenAPI studyAIAPI() { + return new OpenAPI() + .info(new Info() + .title("StudyAI API") + .description("API documentation for StudyAI project") + .version("1.0.0")); + } +} From 09a0288923ab8e1db3f5efb1ff7789783093e4c5 Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Wed, 22 Oct 2025 17:42:31 +0200 Subject: [PATCH 11/13] test: ci by Anais --- backend/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/README.md b/backend/README.md index e69de29..3d0a031 100644 --- a/backend/README.md +++ b/backend/README.md @@ -0,0 +1 @@ +# Début du CI/CD \ No newline at end of file From be7cef02f4b4803eab38d0ae18e4510355eaa6d1 Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Thu, 23 Oct 2025 11:29:53 +0200 Subject: [PATCH 12/13] feat: change folder of CI/CD from root to web folder --- frontend/web/.github/workflows/ci.yml | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 frontend/web/.github/workflows/ci.yml diff --git a/frontend/web/.github/workflows/ci.yml b/frontend/web/.github/workflows/ci.yml new file mode 100644 index 0000000..a127ab9 --- /dev/null +++ b/frontend/web/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: NextJS CI + +on: + push: + branches: [ "dev" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x, 22.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm ci + - run: npm install + - run: npm run lint + - run: npm run build From bba6053c86a108e825076f7b4ea68c74263f9c37 Mon Sep 17 00:00:00 2001 From: Bio Paul Kobena Date: Thu, 23 Oct 2025 11:39:59 +0200 Subject: [PATCH 13/13] fix: ci/cd for nextjs --- frontend/web/.github/workflows/ci.yml | 41 +++++++++++++-------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/frontend/web/.github/workflows/ci.yml b/frontend/web/.github/workflows/ci.yml index a127ab9..abab7ae 100644 --- a/frontend/web/.github/workflows/ci.yml +++ b/frontend/web/.github/workflows/ci.yml @@ -1,32 +1,31 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs +# CI/CD pour voir si tout est ok dans notre projet +# Ce script s'exécute automatiquement lorsqu'on fait push sur les différentes branches ou un pull_request sur les différentes branches énumérées -name: NextJS CI +name: CI/CD for Next.js on: push: - branches: [ "dev" ] + branches: ["dev", "frontend", "dev-reset"] pull_request: - branches: [ "master" ] + branches: [ "master", "dev", "dev-reset" ] jobs: build: - runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 - strategy: - matrix: - node-version: [18.x, 20.x, 22.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + - name: Install dependencies + run: npm install + # Pas de test dans notre cas, donc cette ligne ne sera pas utilisée + - name: Run tests + run: npm run test --if-present - steps: - - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npm install - - run: npm run lint - - run: npm run build + # Test si on a pas de problème de syntaxe dans notre code + - name: Test if lint is ok + run: npm run lint + + # Ce run permet de tester si + - name: Build project + run: npm run build