From 0638983d2394cea2e5a48d762ac9e495d8d77baf Mon Sep 17 00:00:00 2001 From: KADI JOLIE Date: Tue, 24 Mar 2026 17:12:22 +0100 Subject: [PATCH 01/18] je fais un commit --- .classpath | 40 +++++ .gitignore | 1 + .project | 23 +++ .settings/org.eclipse.jdt.core.prefs | 8 + .settings/org.eclipse.m2e.core.prefs | 4 + data.old/test.log | 18 +++ data.old/test.properties | 5 + data.old/test.script | 62 +++++++ data/test.lck | Bin 0 -> 16 bytes data/test.log | 0 data/test.properties | 5 + data/test.script | 70 ++++++++ pom.xml | 15 ++ .../fr/istic/taa/jaxrs/TestApplication.java | 2 + .../java/fr/istic/taa/jaxrs/dao/AdminDao.java | 11 ++ .../fr/istic/taa/jaxrs/dao/ClientDao.java | 11 ++ .../java/fr/istic/taa/jaxrs/dao/EventDao.java | 18 +++ .../fr/istic/taa/jaxrs/dao/ManagerDao.java | 24 +++ .../fr/istic/taa/jaxrs/dao/TicketDao.java | 60 +++++++ .../java/fr/istic/taa/jaxrs/dao/UserDao.java | 59 +++++++ .../dao/generic/EntityManagerHelper.java | 2 +- .../java/fr/istic/taa/jaxrs/domain/Admin.java | 35 ++++ .../fr/istic/taa/jaxrs/domain/Client.java | 40 +++++ .../java/fr/istic/taa/jaxrs/domain/Event.java | 151 ++++++++++++++++++ .../fr/istic/taa/jaxrs/domain/Manager.java | 43 +++++ .../fr/istic/taa/jaxrs/domain/Ticket.java | 111 +++++++++++++ .../fr/istic/taa/jaxrs/domain/TicketId.java | 43 +++++ .../java/fr/istic/taa/jaxrs/domain/User.java | 112 +++++++++++++ .../taa/jaxrs/jpa/EntityManagerHelper.java | 50 ++++++ .../java/fr/istic/taa/jaxrs/jpa/JpaTest.java | 99 ++++++++++++ .../fr/istic/taa/jaxrs/rest/UserResource.java | 49 ++++++ .../istic/taa/jaxrs/service/AdminService.java | 12 ++ .../taa/jaxrs/service/ClientService.java | 5 + .../istic/taa/jaxrs/service/EventService.java | 9 ++ .../taa/jaxrs/service/TicketService.java | 35 ++++ .../istic/taa/jaxrs/service/UserService.java | 44 +++++ src/main/resources/META-INF/persistence.xml | 81 +++------- 37 files changed, 1297 insertions(+), 60 deletions(-) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 data.old/test.log create mode 100644 data.old/test.properties create mode 100644 data.old/test.script create mode 100644 data/test.lck create mode 100644 data/test.log create mode 100644 data/test.properties create mode 100644 data/test.script create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/AdminDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Admin.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Client.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Event.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Manager.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/User.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/jpa/EntityManagerHelper.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/AdminService.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/ClientService.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/EventService.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/TicketService.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/UserService.java diff --git a/.classpath b/.classpath new file mode 100644 index 00000000..f0e98045 --- /dev/null +++ b/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project new file mode 100644 index 00000000..f2be8237 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + JaxRSOpenAPI + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..2af1e7b9 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..f897a7f1 --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/data.old/test.log b/data.old/test.log new file mode 100644 index 00000000..c730891c --- /dev/null +++ b/data.old/test.log @@ -0,0 +1,18 @@ +/*C2*/SET SCHEMA PUBLIC +DISCONNECT +/*C3*/SET SCHEMA PUBLIC +DELETE FROM USER WHERE USERID=52 +COMMIT +DISCONNECT +/*C4*/SET SCHEMA PUBLIC +DISCONNECT +/*C5*/SET SCHEMA PUBLIC +DISCONNECT +/*C6*/SET SCHEMA PUBLIC +DISCONNECT +/*C7*/SET SCHEMA PUBLIC +DISCONNECT +/*C8*/SET SCHEMA PUBLIC +DISCONNECT +/*C9*/SET SCHEMA PUBLIC +DISCONNECT diff --git a/data.old/test.properties b/data.old/test.properties new file mode 100644 index 00000000..9644c456 --- /dev/null +++ b/data.old/test.properties @@ -0,0 +1,5 @@ +#HSQL Database Engine 2.7.2 +#Fri Feb 20 03:06:55 CET 2026 +modified=yes +tx_timestamp=88 +version=2.7.2 diff --git a/data.old/test.script b/data.old/test.script new file mode 100644 index 00000000..869f029f --- /dev/null +++ b/data.old/test.script @@ -0,0 +1,62 @@ +SET DATABASE UNIQUE NAME HSQLDB9C78660004 +SET DATABASE DEFAULT RESULT MEMORY ROWS 0 +SET DATABASE EVENT LOG LEVEL 0 +SET DATABASE TRANSACTION CONTROL LOCKS +SET DATABASE DEFAULT ISOLATION LEVEL READ COMMITTED +SET DATABASE TRANSACTION ROLLBACK ON CONFLICT TRUE +SET DATABASE TEXT TABLE DEFAULTS '' +SET DATABASE SQL NAMES FALSE +SET DATABASE SQL RESTRICT EXEC FALSE +SET DATABASE SQL REFERENCES FALSE +SET DATABASE SQL SIZE TRUE +SET DATABASE SQL TYPES FALSE +SET DATABASE SQL TDC DELETE TRUE +SET DATABASE SQL TDC UPDATE TRUE +SET DATABASE SQL SYS INDEX NAMES TRUE +SET DATABASE SQL CONCAT NULLS TRUE +SET DATABASE SQL UNIQUE NULLS TRUE +SET DATABASE SQL CONVERT TRUNCATE TRUE +SET DATABASE SQL AVG SCALE 0 +SET DATABASE SQL DOUBLE NAN TRUE +SET FILES WRITE DELAY 500 MILLIS +SET FILES BACKUP INCREMENT TRUE +SET FILES CACHE SIZE 10000 +SET FILES CACHE ROWS 50000 +SET FILES SCALE 32 +SET FILES LOB SCALE 32 +SET FILES DEFRAG 0 +SET FILES NIO TRUE +SET FILES NIO SIZE 256 +SET FILES LOG TRUE +SET FILES LOG SIZE 50 +SET FILES CHECK 88 +SET DATABASE COLLATION "SQL_TEXT" PAD SPACE +CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e' +ALTER USER SA SET LOCAL TRUE +CREATE SCHEMA PUBLIC AUTHORIZATION DBA +CREATE SEQUENCE PUBLIC.EVENT_SEQ AS INTEGER START WITH 1 INCREMENT BY 50 +CREATE SEQUENCE PUBLIC.USER_SEQ AS INTEGER START WITH 1 INCREMENT BY 50 +CREATE MEMORY TABLE PUBLIC.ADMIN(USERID BIGINT NOT NULL PRIMARY KEY) +CREATE MEMORY TABLE PUBLIC.CLIENT(USERID BIGINT NOT NULL PRIMARY KEY,STATUTCLIENT VARCHAR(255)) +CREATE MEMORY TABLE PUBLIC.EVENT(EVENTID BIGINT NOT NULL PRIMARY KEY,MANAGER_USERID BIGINT) +CREATE MEMORY TABLE PUBLIC.MANAGER(USERID BIGINT NOT NULL PRIMARY KEY,STATUTMANAGER VARCHAR(255)) +CREATE MEMORY TABLE PUBLIC.TICKET(DATEACHAT DATE,DATEANNULATION DATE,DATEREMBOURSEMENT DATE,NUMEROPLACE INTEGER NOT NULL,PRIX NUMERIC(38,2),EVENTID BIGINT NOT NULL,USERID BIGINT NOT NULL,STATUT VARCHAR(255),PRIMARY KEY(EVENTID,USERID),CONSTRAINT FKG99AEFCEA91OV184GCQ27RW38 FOREIGN KEY(USERID) REFERENCES PUBLIC.CLIENT(USERID),CONSTRAINT FKMCDJ38KCLK095O7XCSRQ1L6PL FOREIGN KEY(EVENTID) REFERENCES PUBLIC.EVENT(EVENTID)) +CREATE MEMORY TABLE PUBLIC.USER(DATENAISS DATE,TEL BIGINT NOT NULL,USERID BIGINT NOT NULL PRIMARY KEY,EMAIL VARCHAR(255),MDP VARCHAR(255),NOM VARCHAR(255),PRENOM VARCHAR(255)) +ALTER TABLE PUBLIC.ADMIN ADD CONSTRAINT FKJOAV33P64SUIKUB3369FPAJY4 FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER TABLE PUBLIC.CLIENT ADD CONSTRAINT FKMEGT8W509PVKVJOTT5J6PVULQ FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER TABLE PUBLIC.EVENT ADD CONSTRAINT FKPROJTK8GIX7GKR8YL2L2UWF4E FOREIGN KEY(MANAGER_USERID) REFERENCES PUBLIC.MANAGER(USERID) +ALTER TABLE PUBLIC.MANAGER ADD CONSTRAINT FK4K4DKJ2CBEM84XEDBYQ0HCVKL FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1 +ALTER SEQUENCE PUBLIC.EVENT_SEQ RESTART WITH 1 +ALTER SEQUENCE PUBLIC.USER_SEQ RESTART WITH 551 +SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC +GRANT DBA TO SA +SET SCHEMA SYSTEM_LOBS +INSERT INTO BLOCKS VALUES(0,2147483647,0) +SET SCHEMA PUBLIC +INSERT INTO USER VALUES(NULL,0,52,NULL,NULL,'Ange','Stephanie') diff --git a/data/test.lck b/data/test.lck new file mode 100644 index 0000000000000000000000000000000000000000..c7d1cd877fa07218d70488198648b88866264924 GIT binary patch literal 16 XcmeYW4)pQyclKsrV4SNk_c12`B`O4| literal 0 HcmV?d00001 diff --git a/data/test.log b/data/test.log new file mode 100644 index 00000000..e69de29b diff --git a/data/test.properties b/data/test.properties new file mode 100644 index 00000000..b15b13f5 --- /dev/null +++ b/data/test.properties @@ -0,0 +1,5 @@ +#HSQL Database Engine 2.7.2 +#Fri Mar 13 17:14:35 CET 2026 +modified=no +tx_timestamp=215 +version=2.7.2 diff --git a/data/test.script b/data/test.script new file mode 100644 index 00000000..356d46bb --- /dev/null +++ b/data/test.script @@ -0,0 +1,70 @@ +SET DATABASE UNIQUE NAME HSQLDB9C7A129D76 +SET DATABASE DEFAULT RESULT MEMORY ROWS 0 +SET DATABASE EVENT LOG LEVEL 0 +SET DATABASE TRANSACTION CONTROL LOCKS +SET DATABASE DEFAULT ISOLATION LEVEL READ COMMITTED +SET DATABASE TRANSACTION ROLLBACK ON CONFLICT TRUE +SET DATABASE TEXT TABLE DEFAULTS '' +SET DATABASE SQL NAMES FALSE +SET DATABASE SQL RESTRICT EXEC FALSE +SET DATABASE SQL REFERENCES FALSE +SET DATABASE SQL SIZE TRUE +SET DATABASE SQL TYPES FALSE +SET DATABASE SQL TDC DELETE TRUE +SET DATABASE SQL TDC UPDATE TRUE +SET DATABASE SQL SYS INDEX NAMES TRUE +SET DATABASE SQL CONCAT NULLS TRUE +SET DATABASE SQL UNIQUE NULLS TRUE +SET DATABASE SQL CONVERT TRUNCATE TRUE +SET DATABASE SQL AVG SCALE 0 +SET DATABASE SQL DOUBLE NAN TRUE +SET FILES WRITE DELAY 500 MILLIS +SET FILES BACKUP INCREMENT TRUE +SET FILES CACHE SIZE 10000 +SET FILES CACHE ROWS 50000 +SET FILES SCALE 32 +SET FILES LOB SCALE 32 +SET FILES DEFRAG 0 +SET FILES NIO TRUE +SET FILES NIO SIZE 256 +SET FILES LOG TRUE +SET FILES LOG SIZE 50 +SET FILES CHECK 215 +SET DATABASE COLLATION "SQL_TEXT" PAD SPACE +CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e' +ALTER USER SA SET LOCAL TRUE +CREATE SCHEMA PUBLIC AUTHORIZATION DBA +CREATE SEQUENCE PUBLIC.EVENT_SEQ AS INTEGER START WITH 1 INCREMENT BY 50 +CREATE SEQUENCE PUBLIC.USER_SEQ AS INTEGER START WITH 1 INCREMENT BY 50 +CREATE MEMORY TABLE PUBLIC.ADMIN(USERID BIGINT NOT NULL PRIMARY KEY) +CREATE MEMORY TABLE PUBLIC.CLIENT(USERID BIGINT NOT NULL PRIMARY KEY,STATUTCLIENT VARCHAR(255)) +CREATE MEMORY TABLE PUBLIC.EVENT(EVENTID BIGINT NOT NULL PRIMARY KEY,MANAGER_USERID BIGINT) +CREATE MEMORY TABLE PUBLIC.MANAGER(USERID BIGINT NOT NULL PRIMARY KEY,STATUTMANAGER VARCHAR(255)) +CREATE MEMORY TABLE PUBLIC.TICKET(DATEACHAT DATE,DATEANNULATION DATE,DATEREMBOURSEMENT DATE,NUMEROPLACE INTEGER NOT NULL,PRIX NUMERIC(38,2),EVENTID BIGINT NOT NULL,USERID BIGINT NOT NULL,STATUT VARCHAR(255),PRIMARY KEY(EVENTID,USERID),CONSTRAINT FKG99AEFCEA91OV184GCQ27RW38 FOREIGN KEY(USERID) REFERENCES PUBLIC.CLIENT(USERID),CONSTRAINT FKMCDJ38KCLK095O7XCSRQ1L6PL FOREIGN KEY(EVENTID) REFERENCES PUBLIC.EVENT(EVENTID)) +CREATE MEMORY TABLE PUBLIC.USER(USERID BIGINT NOT NULL PRIMARY KEY,NOM VARCHAR(255),PRENOM VARCHAR(255)) +ALTER TABLE PUBLIC.ADMIN ADD CONSTRAINT FKJOAV33P64SUIKUB3369FPAJY4 FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER TABLE PUBLIC.CLIENT ADD CONSTRAINT FKMEGT8W509PVKVJOTT5J6PVULQ FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER TABLE PUBLIC.EVENT ADD CONSTRAINT FKPROJTK8GIX7GKR8YL2L2UWF4E FOREIGN KEY(MANAGER_USERID) REFERENCES PUBLIC.MANAGER(USERID) +ALTER TABLE PUBLIC.MANAGER ADD CONSTRAINT FK4K4DKJ2CBEM84XEDBYQ0HCVKL FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(USERID) +ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1 +ALTER SEQUENCE PUBLIC.EVENT_SEQ RESTART WITH 1 +ALTER SEQUENCE PUBLIC.USER_SEQ RESTART WITH 451 +SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC +GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC +GRANT DBA TO SA +SET SCHEMA SYSTEM_LOBS +INSERT INTO BLOCKS VALUES(0,2147483647,0) +SET SCHEMA PUBLIC +INSERT INTO USER VALUES(1,'Ange','Stephanie') +INSERT INTO USER VALUES(2,'Ange','Stephanie') +INSERT INTO USER VALUES(52,'Ange','Stephanie') +INSERT INTO USER VALUES(102,'Ange','Stephanie') +INSERT INTO USER VALUES(152,'Ange','Stephanie') +INSERT INTO USER VALUES(202,'Ange','Stephanie') +INSERT INTO USER VALUES(252,'Ange','Stephanie') +INSERT INTO USER VALUES(302,'lo','mori') +INSERT INTO USER VALUES(352,'lo','mori') diff --git a/pom.xml b/pom.xml index 1b1c1ebe..08c4a8db 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,21 @@ swagger-jaxrs2-servlet-initializer-v2 2.2.15 + + + + + mysql + mysql-connector-java + 8.0.22 + + + + + org.mindrot + jbcrypt + 0.4 + diff --git a/src/main/java/fr/istic/taa/jaxrs/TestApplication.java b/src/main/java/fr/istic/taa/jaxrs/TestApplication.java index c479dad0..c505b63e 100644 --- a/src/main/java/fr/istic/taa/jaxrs/TestApplication.java +++ b/src/main/java/fr/istic/taa/jaxrs/TestApplication.java @@ -20,6 +20,7 @@ import java.util.Set; import fr.istic.taa.jaxrs.rest.PetResource; +import fr.istic.taa.jaxrs.rest.UserResource; import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @@ -35,6 +36,7 @@ public Set> getClasses() { clazzes.add(OpenApiResource.class); clazzes.add(PetResource.class); + clazzes.add(UserResource.class); // clazzes.add(AcceptHeaderOpenApiResource.class); diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/AdminDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/AdminDao.java new file mode 100644 index 00000000..3cfc2f93 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/AdminDao.java @@ -0,0 +1,11 @@ +package fr.istic.taa.jaxrs.dao; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.Admin; + +public class AdminDao extends AbstractJpaDao{ + + public AdminDao() { + this.setClazz(Admin.class); + } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java new file mode 100644 index 00000000..815dfff7 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java @@ -0,0 +1,11 @@ +package fr.istic.taa.jaxrs.dao; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.Client; + +public class ClientDao extends AbstractJpaDao{ + + public ClientDao() { + this.setClazz(Client.class); + } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java new file mode 100644 index 00000000..f5afa551 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java @@ -0,0 +1,18 @@ +package fr.istic.taa.jaxrs.dao; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.Event; + +public class EventDao extends AbstractJpaDao { + + public EventDao() { + this.setClazz(Event.class); + } + +// findAll() +// +// searchByCriteria(String keyword, Date date, String lieu) (pour la recherche). +// +// updateValidation(Long id, boolean isValid). + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java new file mode 100644 index 00000000..ce4ed061 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java @@ -0,0 +1,24 @@ +package fr.istic.taa.jaxrs.dao; + +import java.util.List; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.Manager; + +public class ManagerDao extends AbstractJpaDao{ + + public ManagerDao() { + this.setClazz(Manager.class); + } + + //Requete avec JPQL + public List findMangersActifs() { + + String query_jpql = "SELECT m FROM Manager m WHERE m.statut_User = 'actif'"; + + return this.entityManager.createQuery(query_jpql).getResultList(); + } + +} + + diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java new file mode 100644 index 00000000..a58da7d9 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java @@ -0,0 +1,60 @@ +package fr.istic.taa.jaxrs.dao; + +import java.util.Collections; +import java.util.List; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.Ticket; +import fr.istic.taa.jaxrs.domain.TicketId; +import fr.istic.taa.jaxrs.domain.User; +import jakarta.persistence.NoResultException; + +public class TicketDao extends AbstractJpaDao { + + public TicketDao() { + this.setClazz(Ticket.class); + } + + //Requete NamedQuery + public List findByUserIdNamedQuery(Long id) { + try { + return entityManager + .createNamedQuery("Ticket.findByUserId", Ticket.class) + .setParameter("user_id", id) + .getResultList(); + } catch (NoResultException e) { + // Retourne liste vide si aucun utilisateur n'est trouvé + return Collections.emptyList(); + } + } + + // Requête pour voir qui vient à un concert + public List findByEventId(Long eid) { + String query_jpql = "SELECT t FROM Ticket t WHERE t.event.eventId = :event_id"; + try { + return entityManager + .createQuery(query_jpql, Ticket.class) + .setParameter("event_id", eid) + .getResultList(); + + } catch (Exception e) { + return Collections.emptyList(); + } + } + +// save(Ticket t) +// +// delete(Long id) +// +// findByUserId(Long userId) +// +// findById(Long id). + + + //Exemple d'utilisation cle composite + // TicketDao ticketDao = new TicketDao(); + // // K est un TicketId + // TicketId id = new TicketId(userId, concertId); + // Ticket t = ticketDao.findOne(id); + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java new file mode 100644 index 00000000..f6cbebc0 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java @@ -0,0 +1,59 @@ +package fr.istic.taa.jaxrs.dao; + +import java.util.ArrayList; +import java.util.List; + +import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; +import fr.istic.taa.jaxrs.domain.*; +import jakarta.persistence.*; +import jakarta.persistence.criteria.*; + + +public class UserDao extends AbstractJpaDao { + + public UserDao() { + this.setClazz(User.class); + } + + //Requete NamedQuery + public User findByIdNamedQuery(Long id) { + try { + return entityManager + .createNamedQuery("User.findById", User.class) + .setParameter("user_id", id) + .getSingleResult(); + } catch (NoResultException e) { + // Retourne null si aucun utilisateur n'est trouvé + return null; + } + } + + //Requete avec JPQL + public User findByEmail(String email) { + + String query_jpql = "SELECT u FROM User u WHERE u.email = :emailValue"; + try { + return entityManager.createQuery(query_jpql, User.class) + .setParameter("emailValue", email) + .getSingleResult(); + } catch (NoResultException e) { + // Retourne null si aucun utilisateur n'est trouvé + return null; + } + } + + // Criteria Query : On construit la requête avec du code Java. + public List findAllUser() { + + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery cq = cb.createQuery(User.class); + + Root userRoot = cq.from(User.class); + + cq.select(userRoot); + + return entityManager.createQuery(cq).getResultList(); + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/generic/EntityManagerHelper.java b/src/main/java/fr/istic/taa/jaxrs/dao/generic/EntityManagerHelper.java index a9950dc2..5ea39e97 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/generic/EntityManagerHelper.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/generic/EntityManagerHelper.java @@ -10,7 +10,7 @@ public class EntityManagerHelper { private static final ThreadLocal threadLocal; static { - emf = Persistence.createEntityManagerFactory("dev"); + emf = Persistence.createEntityManagerFactory("mysql"); threadLocal = new ThreadLocal(); } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java b/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java new file mode 100644 index 00000000..4b3192ca --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java @@ -0,0 +1,35 @@ +package fr.istic.taa.jaxrs.domain; + +import java.io.Serializable; +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.OneToMany; + +@Entity +public class Admin extends User implements Serializable { + + private List events; + + + //GETTERS - SETTERS + + @OneToMany(mappedBy = "admin", cascade = CascadeType.PERSIST) + public List getEvents() { + return events; + } + public void setEvents(List events) { + this.events = events; + } + + //ToString Admin + @Override + public String toString() { + return "Admin [events=" + events + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" + + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + ", statut_User=" + statut_user + "]"; + } +} + diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Client.java b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java new file mode 100644 index 00000000..3e0dee83 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java @@ -0,0 +1,40 @@ +package fr.istic.taa.jaxrs.domain; + +import java.io.Serializable; +import java.util.List; + +import jakarta.persistence.*; + +@Entity +public class Client extends User implements Serializable{ + + private List tickets; + + + //GETTERS - SETTERS + + @OneToMany(mappedBy = "client", cascade = CascadeType.PERSIST) + public List getTickets() { + return tickets; + } + public void setTickets(List tickets) { + this.tickets = tickets; + } + + //ToString Client + @Override + public String toString() { + return "Client [tickets=" + tickets + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" + + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + ", statut_User=" + statut_user + "]"; + } + + +// //CONSTRUCTEURS +// public Client() { +// super(); +// } +// public Client(String statutClient) { +// this.statutClient = statutClient; +// } +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Event.java b/src/main/java/fr/istic/taa/jaxrs/domain/Event.java new file mode 100644 index 00000000..6f7b3d57 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Event.java @@ -0,0 +1,151 @@ +package fr.istic.taa.jaxrs.domain; + +import java.io.Serializable; +import java.time.LocalDate; +import java.util.List; +import jakarta.persistence.*; + +@Entity +public class Event implements Serializable { + + private long eventId; + private String nom; + private String description; + private String artiste; + private String lieu; + private LocalDate dateConcert; + private String genreMusical; + private int nbPlaceDispo; + private String dureeConcert; + private String statut; + private LocalDate dateValidation; + private String commentairesAdmin; + private Manager manager; + private Admin admin; + private List tickets; + + + //GETTERS - SETTERS + @Id + @GeneratedValue + public long getEventId() { + return eventId; + } + public void setEventId(long eventId) { + this.eventId = eventId; + } + + @ManyToOne + public Manager getManager() { + return manager; + } + public void setManager(Manager manager) { + this.manager = manager; + } + + @ManyToOne + public Admin getAdmin() { + return admin; + } + public void setAdmin(Admin admin) { + this.admin = admin; + } + + + @OneToMany(mappedBy = "event", cascade = CascadeType.PERSIST) + public List getTickets() { + return tickets; + } + public void setTickets(List tickets) { + this.tickets = tickets; + } + + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getArtiste() { + return artiste; + } + public void setArtiste(String artiste) { + this.artiste = artiste; + } + + public String getLieu() { + return lieu; + } + public void setLieu(String lieu) { + this.lieu = lieu; + } + + public LocalDate getDateConcert() { + return dateConcert; + } + public void setDateConcert(LocalDate dateConcert) { + this.dateConcert = dateConcert; + } + + public String getGenreMusical() { + return genreMusical; + } + public void setGenreMusical(String genreMusical) { + this.genreMusical = genreMusical; + } + + public int getNbPlaceDispo() { + return nbPlaceDispo; + } + public void setNbPlaceDispo(int nbPlaceDispo) { + this.nbPlaceDispo = nbPlaceDispo; + } + + public String getDureeConcert() { + return dureeConcert; + } + public void setDureeConcert(String dureeConcert) { + this.dureeConcert = dureeConcert; + } + + public String getStatut() { + return statut; + } + public void setStatut(String statut) { + this.statut = statut; + } + + public LocalDate getDateValidation() { + return dateValidation; + } + public void setDateValidation(LocalDate dateValidation) { + this.dateValidation = dateValidation; + } + + public String getCommentairesAdmin() { + return commentairesAdmin; + } + public void setCommentairesAdmin(String commentairesAdmin) { + this.commentairesAdmin = commentairesAdmin; + } + + //ToString Event + @Override + public String toString() { + return "Event [eventId=" + eventId + ", nom=" + nom + ", description=" + description + ", artiste=" + artiste + + ", lieu=" + lieu + ", dateConcert=" + dateConcert + ", genreMusical=" + genreMusical + + ", nbPlaceDispo=" + nbPlaceDispo + ", dureeConcert=" + dureeConcert + ", statut=" + statut + + ", dateValidation=" + dateValidation + ", commentairesAdmin=" + commentairesAdmin + ", manager=" + + manager + ", admin=" + admin + ", tickets=" + tickets + "]"; + } + +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java new file mode 100644 index 00000000..8ee2795c --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java @@ -0,0 +1,43 @@ +package fr.istic.taa.jaxrs.domain; + +import java.io.Serializable; +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; + +@Entity +public class Manager extends User implements Serializable { + + private List events; + + + //GETTERS - SETTERS + + @OneToMany(mappedBy = "manager", cascade = CascadeType.PERSIST) + public List getEvents() { + return events; + } + public void setEvents(List events) { + this.events = events; + } + + //ToString Manager + @Override + public String toString() { + return "Manager [events=" + events + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" + + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + ", statut_User=" + statut_user + "]"; + } + +// //CONSTRUCTEURS +// public Manager() { +// super(); +// } +// public Manager(String statutManager) { +// this.setStatutManager(statutManager); +// } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java b/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java new file mode 100644 index 00000000..695ba14d --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java @@ -0,0 +1,111 @@ +package fr.istic.taa.jaxrs.domain; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; + +import jakarta.persistence.*; +/*import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId;*/ + +@Entity +//Requete NamedQuery +@NamedQuery( + name = "Ticket.findByUserId", + query = "SELECT t FROM Ticket t WHERE t.client.userId = :user_id" + ) +public class Ticket implements Serializable { + + @EmbeddedId + private TicketId id; + private int numeroPlace; + private BigDecimal prix; + private String statut; + private LocalDate dateAchat; + private LocalDate dateAnnulation; + private LocalDate dateRemboursement; + + @ManyToOne + @MapsId("userId") + @JoinColumn(name = "userId", nullable = false) + private Client client; + + @ManyToOne + @MapsId("eventId") // Map a TicketId.eventId + @JoinColumn(name = "eventId", nullable = false) + private Event event; + + @Column(precision = 8, scale = 2) + public BigDecimal getPrix() { + return prix; + } + public void setPrix(BigDecimal prix) { + this.prix = prix; + } + + // Getters et Setters + public TicketId getId() { return id; } + public void setId(TicketId id) { this.id = id; } + + public Client getClient() { return client; } + public void setClient(Client client) { this.client = client; } + + public Event getEvent() { return event; } + public void setEvent(Event event) { this.event = event; } + + public int getNumeroPlace() { + return numeroPlace; + } + public void setNumeroPlace(int numeroPlace) { + this.numeroPlace = numeroPlace; + } + + public String getStatut() { + return statut; + } + public void setStatut(String statut) { + this.statut = statut; + } + + public LocalDate getDateAchat() { + return dateAchat; + } + public void setDateAchat(LocalDate dateAchat) { + this.dateAchat = dateAchat; + } + + public LocalDate getDateAnnulation() { + return dateAnnulation; + } + public void setDateAnnulation(LocalDate dateAnnulation) { + this.dateAnnulation = dateAnnulation; + } + + public LocalDate getDateRemboursement() { + return dateRemboursement; + } + public void setDateRemboursement(LocalDate dateRemboursement) { + this.dateRemboursement = dateRemboursement; + } + + public void diminuer() { + // diminuer le nombre de places disponibles + } + @Override + public String toString() { + return "Ticket [id=" + id + ", numeroPlace=" + numeroPlace + ", prix=" + prix + ", statut=" + statut + + ", dateAchat=" + dateAchat + ", dateAnnulation=" + dateAnnulation + ", dateRemboursement=" + + dateRemboursement + ", client=" + client + ", event=" + event + "]"; + } + +} + + +////CONSTRUCTEURS +//public Ticket() {} +//public Ticket(int userId, int eventId) { +// this.id = new TicketId(userId, eventId); +//} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java b/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java new file mode 100644 index 00000000..76716b9e --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java @@ -0,0 +1,43 @@ +package fr.istic.taa.jaxrs.domain; + +import jakarta.persistence.Embeddable; + +import java.io.Serializable; +import java.util.Objects; + +@Embeddable +public class TicketId implements Serializable { + private long userId; + private long eventId; + + + //CONSTRUCTEURS + public TicketId() { + super(); + } + public TicketId(int userId, int eventId) { + this.userId = userId; + this.eventId = eventId; + } + + + //GETTERS - SETTERS + public long getUserId() { return userId; } + public void setUserId(int userId) { this.userId = userId; } + + public long getEventId() { return eventId; } + public void setEventId(int eventId) { this.eventId = eventId; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TicketId ticketId = (TicketId) o; + return userId == ticketId.userId && eventId == ticketId.eventId; + } + + @Override + public int hashCode() { + return Objects.hash(userId, eventId); + } +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/User.java b/src/main/java/fr/istic/taa/jaxrs/domain/User.java new file mode 100644 index 00000000..6e02d0b1 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/User.java @@ -0,0 +1,112 @@ +package fr.istic.taa.jaxrs.domain; + +import jakarta.persistence.*; +import java.io.Serializable; +import java.time.LocalDate; + +@Entity +//Requete NamedQuery +@NamedQuery( + name = "User.findById", + query = "SELECT u FROM User u WHERE u.userId = :user_id" + ) +@Inheritance(strategy = InheritanceType.JOINED) +public class User implements Serializable { + + protected long userId; + protected String nom; + protected String prenom; + protected String email; + protected LocalDate date_naissance; + protected String password; + protected int tel; + protected boolean statut_user; + + + //Getters and Setters + + @Id + @GeneratedValue + public long getUserId() { + return userId; + } + public void setUserId(long userId) { + this.userId = userId; + } + + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + + public String getPrenom() { + return prenom; + } + public void setPrenom(String prenom) { + this.prenom = prenom; + } + + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + + public int getTel() { + return tel; + } + public void setTel(int tel) { + this.tel = tel; + } + + + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } + + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + + public boolean isStatut_user() { + return statut_user; + } + public void setStatut_user(boolean statut_user) { + this.statut_user = statut_user; + } + + + //ToString User + @Override + public String toString() { + return "User [userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + "]"; + } + + /*public User(long userId, String nom, String prenom, String email, long tel, LocalDate dateNaiss, String mdp) { + super(); + this.userId = userId; + this.nom = nom; + this.prenom = prenom; + this.email = email; + this.tel = tel; + this.dateNaiss = dateNaiss; + this.mdp = mdp; + } + + public User() {}*/ +} diff --git a/src/main/java/fr/istic/taa/jaxrs/jpa/EntityManagerHelper.java b/src/main/java/fr/istic/taa/jaxrs/jpa/EntityManagerHelper.java new file mode 100644 index 00000000..89ba91f8 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/jpa/EntityManagerHelper.java @@ -0,0 +1,50 @@ +package fr.istic.taa.jaxrs.jpa; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; + +public class EntityManagerHelper { + + private static final EntityManagerFactory emf; + private static final ThreadLocal threadLocal; + + static { + emf = Persistence.createEntityManagerFactory("mysql"); + threadLocal = new ThreadLocal(); + } + + public static EntityManager getEntityManager() { + EntityManager em = threadLocal.get(); + + if (em == null) { + em = emf.createEntityManager(); + threadLocal.set(em); + } + return em; + } + + public static void closeEntityManager() { + EntityManager em = threadLocal.get(); + if (em != null) { + em.close(); + threadLocal.set(null); + } + } + + public static void closeEntityManagerFactory() { + emf.close(); + } + + public static void beginTransaction() { + getEntityManager().getTransaction().begin(); + } + + public static void rollback() { + getEntityManager().getTransaction().rollback(); + } + + public static void commit() { + getEntityManager().getTransaction().commit(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java b/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java new file mode 100644 index 00000000..ab1055fc --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java @@ -0,0 +1,99 @@ +package fr.istic.taa.jaxrs.jpa; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityTransaction; +import fr.istic.taa.jaxrs.dao.ManagerDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.Manager; +import fr.istic.taa.jaxrs.domain.User; + +public class JpaTest { + + + private EntityManager manager; + + public JpaTest(EntityManager manager) { + this.manager = manager; + } + /** + * @param args + */ + public static void main(String[] args) { + /*EntityManager manager = EntityManagerHelper.getEntityManager(); + + JpaTest test = new JpaTest(manager); + + EntityTransaction tx = manager.getTransaction(); + tx.begin();*/ + + //cree directement l'utilisateur lié + + ManagerDao managerDao = new ManagerDao(); + Manager m = new Manager(); + m.setNom("Dupont"); + m.setPrenom("Jean"); + m.setStatut_user(true); + managerDao.save(m); + System.out.println(managerDao.findAll()); + +// ManagerDao managerDao = new ManagerDao(); +// System.out.println(managerDao.findMangersActifs()); + +// UserDao userDao = new UserDao(); +// System.out.println(userDao.findUsersByNom("Aryath")); + + try { + + // TODO create and persist entity + } catch (Exception e) { + e.printStackTrace(); + } + /*tx.commit(); + + + manager.close(); + EntityManagerHelper.closeEntityManagerFactory();*/ + System.out.println(".. done"); + } + +} + +//package fr.istic.taa.jaxrs.jpa; +// +//import jakarta.persistence.EntityManager; +//import jakarta.persistence.EntityTransaction; +// +//public class JpaTest { +// +// +// private EntityManager manager; +// +// public JpaTest(EntityManager manager) { +// this.manager = manager; +// } +// /** +// * @param args +// */ +// public static void main(String[] args) { +// EntityManager manager = EntityManagerHelper.getEntityManager(); +// +// JpaTest test = new JpaTest(manager); +// +// EntityTransaction tx = manager.getTransaction(); +// tx.begin(); +// +// try { +// +// // TODO create and persist entity +// } catch (Exception e) { +// e.printStackTrace(); +// } +// tx.commit(); +// +// +// manager.close(); +// EntityManagerHelper.closeEntityManagerFactory(); +// System.out.println(".. done"); +// } +// +//} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java new file mode 100644 index 00000000..02b83267 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java @@ -0,0 +1,49 @@ +package fr.istic.taa.jaxrs.rest; + +import org.hibernate.service.spi.InjectService; + +import fr.istic.taa.jaxrs.dao.ManagerDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.Manager; +import fr.istic.taa.jaxrs.domain.User; +import fr.istic.taa.jaxrs.service.UserService; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; + +@Path("user") +@Produces({"application/json", "application/xml"}) +public class UserResource { + + private UserDao userDao = new UserDao(); + private UserService userService = new UserService(); + + @GET + @Path("/{user_id}") + public Response getUserById(@PathParam("user_id") Long user_id) { + // appel DAO + User user = userDao.findByIdNamedQuery(user_id); + + if(user != null){ + return Response.ok(user).build(); + } + return Response.status(Response.Status.NOT_FOUND).build(); + } + + + @POST + @Path("/inscrire") + @Consumes("application/json") + //@Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) + public Response inscription(User newUser) { + try { + userService.inscription(newUser); + return Response.status(Response.Status.CREATED).entity(newUser).build(); + } catch (Exception e) { + // TODO: handle exception + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + // add pet + //return Response.ok().entity("SUCCESS").build(); + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java b/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java new file mode 100644 index 00000000..92f5b4d5 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java @@ -0,0 +1,12 @@ +package fr.istic.taa.jaxrs.service; + +public class AdminService { + +// AdminService +// Regroupe les actions de modération. +// +// validerEvenement(Long concertId) : Appelle ConcertDao pour passer le statut à "Validé". Peut envoyer un mail de notification à l'organisateur. +// +// gererAccesUtilisateur(Long userId, boolean suspendre) : Appelle UserDao pour modifier le statut du compte. + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java new file mode 100644 index 00000000..d4fcf5a0 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java @@ -0,0 +1,5 @@ +package fr.istic.taa.jaxrs.service; + +public class ClientService { + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/EventService.java b/src/main/java/fr/istic/taa/jaxrs/service/EventService.java new file mode 100644 index 00000000..07c00852 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/EventService.java @@ -0,0 +1,9 @@ +package fr.istic.taa.jaxrs.service; + +public class EventService { + +// ConcertService +// rechercherConcerts(String query) : Filtre les concerts disponibles (et validés par l'admin !) via le ConcertDao. + + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java b/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java new file mode 100644 index 00000000..d3395345 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java @@ -0,0 +1,35 @@ +package fr.istic.taa.jaxrs.service; + +public class TicketService { + +// TicketService +// +// C'est la partie la plus complexe car elle touche à l'argent et aux places disponibles. +// +// acheterTicket(Long userId, Long concertId) : +// +// Vérifie si le concert est complet. +// +// Décrémente le nombre de places via ConcertDao. +// +// Crée le ticket via TicketDao. +// +// annulerEtRembourser(Long ticketId) : +// +// Vérifie si la date du concert n'est pas passée. +// +// Déclenche la logique de remboursement (API bancaire ou avoir). +// +// Supprime/Archive le ticket via TicketDao. +// +// Réaugmente le nombre de places du concert. +// +// genererPdfTicket(Long ticketId) : Récupère les infos du ticket et transforme les données en flux PDF (pour le téléchargement). + + +// public void annulerAchat(Long userId, Long concertId) { +// TicketId id = new TicketId(userId, concertId); +// ticketDao.deleteById(id); +// } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/UserService.java b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java new file mode 100644 index 00000000..f0139e57 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java @@ -0,0 +1,44 @@ +package fr.istic.taa.jaxrs.service; + +import org.mindrot.jbcrypt.BCrypt; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.User; + +public class UserService { + + //1-proposition d'implementation pour methode s'inscrire + public void inscription(User user) throws Exception { + UserDao userDao = new UserDao(); + + if (userDao.findByEmail(user.getEmail()) != null) { + throw new Exception("Email déjà utilisé"); + } + String hashed = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()); + user.setPassword(hashed); + userDao.save(user); // Appel simple au DAO + } + + + //2-proposition d'implementation pour methode seConnecter +// public User seConnecter(String email, String motDePasseSaisi) { +// // 1. On demande au DAO de nous donner l'utilisateur par son email +// User user = userReferenceDao.findByEmail(email); +// +// if (user == null) { +// throw new RuntimeException("Utilisateur non trouvé"); +// } +// +// // 2. C'est ICI qu'on utilise la fonction de comparaison +// // On ne fait JAMAIS "if (motDePasseSaisi == user.getPassword())" +// boolean match = BCrypt.checkpw(motDePasseSaisi, user.getPassword()); +// +// if (!match) { +// throw new RuntimeException("Mot de passe incorrect"); +// } +// +// return user; // Connexion réussie +// } + + //3-Déconnexion Invalide la session en cours ou supprime le token (pas besoin du DAO ici en général). + +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 7277b7dd..5997d427 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -4,64 +4,27 @@ xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> - - org.hibernate.jpa.HibernatePersistenceProvider - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From d3e3db227c39debe756bdd3f503eeabaf6d69365 Mon Sep 17 00:00:00 2001 From: KADI JOLIE Date: Wed, 8 Apr 2026 23:30:02 +0200 Subject: [PATCH 02/18] mes modifications --- data/test.lck | Bin 16 -> 0 bytes data/test.properties | 4 +- data/test.script | 2 +- pom.xml | 6 + .../fr/istic/taa/jaxrs/TestApplication.java | 2 + .../fr/istic/taa/jaxrs/dao/ClientDao.java | 47 ++++++++ .../fr/istic/taa/jaxrs/dao/ManagerDao.java | 17 ++- .../java/fr/istic/taa/jaxrs/dao/UserDao.java | 63 +++++------ .../fr/istic/taa/jaxrs/domain/Client.java | 14 +-- .../fr/istic/taa/jaxrs/domain/Manager.java | 6 + .../java/fr/istic/taa/jaxrs/domain/User.java | 17 ++- .../fr/istic/taa/jaxrs/dto/ConnexionDTO.java | 20 ++++ .../istic/taa/jaxrs/dto/InscriptionDTO.java | 64 +++++++++++ .../istic/taa/jaxrs/dto/ModificationDTO.java | 40 +++++++ .../fr/istic/taa/jaxrs/dto/PasswordDTO.java | 22 ++++ .../istic/taa/jaxrs/dto/UserResponseDTO.java | 81 ++++++++++++++ .../istic/taa/jaxrs/rest/ClientRessource.java | 49 +++++++++ .../fr/istic/taa/jaxrs/rest/UserResource.java | 70 +++++++----- .../taa/jaxrs/service/ClientService.java | 55 ++++++++++ .../taa/jaxrs/service/ManagerService.java | 30 +++++ .../istic/taa/jaxrs/service/UserService.java | 103 +++++++++++++----- 21 files changed, 599 insertions(+), 113 deletions(-) delete mode 100644 data/test.lck create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java diff --git a/data/test.lck b/data/test.lck deleted file mode 100644 index c7d1cd877fa07218d70488198648b88866264924..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16 XcmeYW4)pQyclKsrV4SNk_c12`B`O4| diff --git a/data/test.properties b/data/test.properties index b15b13f5..ee984c5f 100644 --- a/data/test.properties +++ b/data/test.properties @@ -1,5 +1,5 @@ #HSQL Database Engine 2.7.2 -#Fri Mar 13 17:14:35 CET 2026 +#Wed Apr 08 12:36:51 CEST 2026 modified=no -tx_timestamp=215 +tx_timestamp=270 version=2.7.2 diff --git a/data/test.script b/data/test.script index 356d46bb..357ee08e 100644 --- a/data/test.script +++ b/data/test.script @@ -29,7 +29,7 @@ SET FILES NIO TRUE SET FILES NIO SIZE 256 SET FILES LOG TRUE SET FILES LOG SIZE 50 -SET FILES CHECK 215 +SET FILES CHECK 270 SET DATABASE COLLATION "SQL_TEXT" PAD SPACE CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e' ALTER USER SA SET LOCAL TRUE diff --git a/pom.xml b/pom.xml index 08c4a8db..e802092b 100644 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,12 @@ jbcrypt 0.4 + + + + + + diff --git a/src/main/java/fr/istic/taa/jaxrs/TestApplication.java b/src/main/java/fr/istic/taa/jaxrs/TestApplication.java index c505b63e..45930485 100644 --- a/src/main/java/fr/istic/taa/jaxrs/TestApplication.java +++ b/src/main/java/fr/istic/taa/jaxrs/TestApplication.java @@ -19,6 +19,7 @@ import java.util.HashSet; import java.util.Set; +import fr.istic.taa.jaxrs.rest.ClientRessource; import fr.istic.taa.jaxrs.rest.PetResource; import fr.istic.taa.jaxrs.rest.UserResource; import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; @@ -37,6 +38,7 @@ public Set> getClasses() { clazzes.add(OpenApiResource.class); clazzes.add(PetResource.class); clazzes.add(UserResource.class); + clazzes.add(ClientRessource.class); // clazzes.add(AcceptHeaderOpenApiResource.class); diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java index 815dfff7..0f04434f 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java @@ -2,10 +2,57 @@ import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.Client; +import jakarta.persistence.*; public class ClientDao extends AbstractJpaDao{ public ClientDao() { this.setClazz(Client.class); } + + +////Requete avec JPQL +// public Client findByEmail(String email) { +// +// String query_jpql = "SELECT c FROM Client c WHERE c.email = :emailValue"; +// try { +// return entityManager.createQuery(query_jpql, Client.class) +// .setParameter("emailValue", email) +// .getSingleResult(); +// } catch (NoResultException e) { +// // Retourne null si aucun utilisateur n'est trouvé +// return null; +// } +// } +// + + + //Requete NamedQuery +// public Client findByIdNamedQuery(Long id) { +// try { +// return entityManager +// .createNamedQuery("Client.findById", Client.class) +// .setParameter("user_id", id) +// .getSingleResult(); +// } catch (NoResultException e) { +// // Retourne null si aucun utilisateur n'est trouvé +// return null; +// } +// } +// +// // Criteria Query : On construit la requête avec du code Java. +// public List findAllUser() { +// +// CriteriaBuilder cb = entityManager.getCriteriaBuilder(); +// +// CriteriaQuery cq = cb.createQuery(Client.class); +// +// Root userRoot = cq.from(Client.class); +// +// cq.select(userRoot); +// +// return entityManager.createQuery(cq).getResultList(); +// } + + } diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java index ce4ed061..44417b77 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/ManagerDao.java @@ -1,9 +1,8 @@ package fr.istic.taa.jaxrs.dao; -import java.util.List; - import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.Manager; +import jakarta.persistence.NoResultException; public class ManagerDao extends AbstractJpaDao{ @@ -11,13 +10,13 @@ public ManagerDao() { this.setClazz(Manager.class); } - //Requete avec JPQL - public List findMangersActifs() { - - String query_jpql = "SELECT m FROM Manager m WHERE m.statut_User = 'actif'"; - - return this.entityManager.createQuery(query_jpql).getResultList(); - } +// //Requete avec JPQL +// public List findMangersActifs() { +// +// String query_jpql = "SELECT m FROM Manager m WHERE m.statut_User = 'actif'"; +// +// return this.entityManager.createQuery(query_jpql).getResultList(); +// } } diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java index f6cbebc0..1a7e2765 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java @@ -1,12 +1,8 @@ package fr.istic.taa.jaxrs.dao; -import java.util.ArrayList; -import java.util.List; - import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.*; import jakarta.persistence.*; -import jakarta.persistence.criteria.*; public class UserDao extends AbstractJpaDao { @@ -16,11 +12,11 @@ public UserDao() { } //Requete NamedQuery - public User findByIdNamedQuery(Long id) { + public User findByEmailNamedQuery(String email) { try { return entityManager - .createNamedQuery("User.findById", User.class) - .setParameter("user_id", id) + .createNamedQuery("User.findByEmail", User.class) + .setParameter("emailValue", email) .getSingleResult(); } catch (NoResultException e) { // Retourne null si aucun utilisateur n'est trouvé @@ -28,32 +24,31 @@ public User findByIdNamedQuery(Long id) { } } - //Requete avec JPQL - public User findByEmail(String email) { - - String query_jpql = "SELECT u FROM User u WHERE u.email = :emailValue"; - try { - return entityManager.createQuery(query_jpql, User.class) - .setParameter("emailValue", email) - .getSingleResult(); - } catch (NoResultException e) { - // Retourne null si aucun utilisateur n'est trouvé - return null; - } - } - - // Criteria Query : On construit la requête avec du code Java. - public List findAllUser() { - - CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - - CriteriaQuery cq = cb.createQuery(User.class); - - Root userRoot = cq.from(User.class); - - cq.select(userRoot); - - return entityManager.createQuery(cq).getResultList(); - } +// //Requete NamedQuery +// public User findByIdNamedQuery(Long id) { +// try { +// return entityManager +// .createNamedQuery("User.findById", User.class) +// .setParameter("user_id", id) +// .getSingleResult(); +// } catch (NoResultException e) { +// // Retourne null si aucun utilisateur n'est trouvé +// return null; +// } +// } +// +// // Criteria Query : On construit la requête avec du code Java. +// public List findAllUser() { +// +// CriteriaBuilder cb = entityManager.getCriteriaBuilder(); +// +// CriteriaQuery cq = cb.createQuery(User.class); +// +// Root userRoot = cq.from(User.class); +// +// cq.select(userRoot); +// +// return entityManager.createQuery(cq).getResultList(); +// } } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Client.java b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java index 3e0dee83..43ea15d6 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Client.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java @@ -6,6 +6,11 @@ import jakarta.persistence.*; @Entity +////Requete NamedQuery +//@NamedQuery( +// name = "Client.findById", +// query = "SELECT c FROM Client c WHERE c.userId = :user_id" +// ) public class Client extends User implements Serializable{ private List tickets; @@ -28,13 +33,4 @@ public String toString() { + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + ", statut_User=" + statut_user + "]"; } - - -// //CONSTRUCTEURS -// public Client() { -// super(); -// } -// public Client(String statutClient) { -// this.statutClient = statutClient; -// } } \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java index 8ee2795c..22c04715 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java @@ -7,9 +7,15 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.NamedQuery; import jakarta.persistence.OneToMany; @Entity +//Requete NamedQuery +@NamedQuery( + name = "Manager.findByEmail", + query = "SELECT m FROM Manager m WHERE m.email = :emailValue" + ) public class Manager extends User implements Serializable { private List events; diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/User.java b/src/main/java/fr/istic/taa/jaxrs/domain/User.java index 6e02d0b1..12bf0057 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/User.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/User.java @@ -4,11 +4,18 @@ import java.io.Serializable; import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + + + @Entity -//Requete NamedQuery @NamedQuery( - name = "User.findById", - query = "SELECT u FROM User u WHERE u.userId = :user_id" + name = "User.findByEmail", + query = "SELECT u FROM User u WHERE u.email = :emailValue" ) @Inheritance(strategy = InheritanceType.JOINED) public class User implements Serializable { @@ -66,7 +73,9 @@ public void setTel(int tel) { this.tel = tel; } - + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") public LocalDate getDate_naissance() { return date_naissance; } diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java new file mode 100644 index 00000000..be929111 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java @@ -0,0 +1,20 @@ +package fr.istic.taa.jaxrs.dto; + +public class ConnexionDTO { + private String email; + private String password; + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java new file mode 100644 index 00000000..925b2297 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java @@ -0,0 +1,64 @@ +package fr.istic.taa.jaxrs.dto; + +import java.time.LocalDate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +public class InscriptionDTO { + + private String nom; + private String prenom; + private String email; + private String password; + private int tel; + private LocalDate date_naissance; + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + public String getPrenom() { + return prenom; + } + public void setPrenom(String prenom) { + this.prenom = prenom; + } + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + public int getTel() { + return tel; + } + public void setTel(int tel) { + this.tel = tel; + } + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java new file mode 100644 index 00000000..de9c4198 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java @@ -0,0 +1,40 @@ +package fr.istic.taa.jaxrs.dto; + +import java.time.LocalDate; + +public class ModificationDTO { + + private String nom; + private String prenom; + private String tel; + private LocalDate date_naissance; + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + public String getPrenom() { + return prenom; + } + public void setPrenom(String prenom) { + this.prenom = prenom; + } + + public String getTel() { + return tel; + } + public void setTel(String tel) { + this.tel = tel; + } + + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java new file mode 100644 index 00000000..6a1df18a --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java @@ -0,0 +1,22 @@ +package fr.istic.taa.jaxrs.dto; + +public class PasswordDTO { + + private String oldPassword; + private String newPassword; + + public String getOldPassword() { + return oldPassword; + } + public void setOldPassword(String oldPassword) { + this.oldPassword = oldPassword; + } + + public String getNewPassword() { + return newPassword; + } + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java new file mode 100644 index 00000000..9447f226 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java @@ -0,0 +1,81 @@ +package fr.istic.taa.jaxrs.dto; + +import java.time.LocalDate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +public class UserResponseDTO { + + private Long id; + private String nom; + private String prenom; + private String email; + private int tel; + private LocalDate date_naissance; + private String role; + protected boolean statut_user; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + public String getPrenom() { + return prenom; + } + public void setPrenom(String prenom) { + this.prenom = prenom; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public int getTel() { + return tel; + } + public void setTel(int tel) { + this.tel = tel; + } + + + public String getRole() { + return role; + } + public void setRole(String role) { + this.role = role; + } + + public boolean isStatut_user() { + return statut_user; + } + public void setStatut_user(boolean statut_user) { + this.statut_user = statut_user; + } + + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } + +} + diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java b/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java new file mode 100644 index 00000000..b5d51942 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java @@ -0,0 +1,49 @@ +package fr.istic.taa.jaxrs.rest; + +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.Client; +import fr.istic.taa.jaxrs.dto.ClientResponseDTO; +import fr.istic.taa.jaxrs.dto.InscriptionDTO; +import fr.istic.taa.jaxrs.dto.UserResponseDTO; +import fr.istic.taa.jaxrs.service.ClientService; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.Response; + +@Path("client") +@Produces({"application/json", "application/xml"}) +public class ClientRessource { + + private ClientService clientService; + + public ClientRessource() { + ClientDao clientDao = new ClientDao(); + UserDao UserDao = new UserDao(); + this.clientService = new ClientService(clientDao, UserDao); + } + + + + @POST + @Path("/inscrire") + @Consumes("application/json") + //@Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) + public Response inscription(InscriptionDTO dto) { + try { + UserResponseDTO response = clientService.inscription(dto); + return Response.status(Response.Status.CREATED).entity(response).build(); + } catch (Exception e) { + // TODO: handle exception + System.out.println(e.getMessage()); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + +} + + + + diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java index 02b83267..4154c0aa 100644 --- a/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java +++ b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java @@ -6,6 +6,9 @@ import fr.istic.taa.jaxrs.dao.UserDao; import fr.istic.taa.jaxrs.domain.Manager; import fr.istic.taa.jaxrs.domain.User; +import fr.istic.taa.jaxrs.dto.ConnexionDTO; +import fr.istic.taa.jaxrs.dto.PasswordDTO; +import fr.istic.taa.jaxrs.dto.UserResponseDTO; import fr.istic.taa.jaxrs.service.UserService; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; @@ -14,36 +17,53 @@ @Produces({"application/json", "application/xml"}) public class UserResource { - private UserDao userDao = new UserDao(); - private UserService userService = new UserService(); + private UserService userService; + + public UserResource() { + UserDao userDao = new UserDao(); + this.userService = new UserService(userDao); + } - @GET - @Path("/{user_id}") - public Response getUserById(@PathParam("user_id") Long user_id) { - // appel DAO - User user = userDao.findByIdNamedQuery(user_id); - - if(user != null){ - return Response.ok(user).build(); - } - return Response.status(Response.Status.NOT_FOUND).build(); - } +// @GET +// @Path("/{user_id}") +// public Response getUserById(@PathParam("user_id") Long user_id) { +// // appel DAO +// User user = userDao.findOne(user_id); +// +// if(user != null){ +// return Response.ok(user).build(); +// } +// return Response.status(Response.Status.NOT_FOUND).build(); +// } + + // Modification mot de passe + @PUT + @Path("/updatePassword/{user_id}") + public Response modifierPassword(@PathParam("user_id") Long user_id, PasswordDTO dto) { + // user contient juste l'ancien et le nouveau password + try { + userService.changerMdp(user_id, dto); + return Response.ok("Mot de passe modifié").build(); + } catch (Exception e) { + return Response.status(400).entity(e.getMessage()).build(); + } + } + @POST - @Path("/inscrire") + @Path("/connexion") @Consumes("application/json") - //@Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) - public Response inscription(User newUser) { - try { - userService.inscription(newUser); - return Response.status(Response.Status.CREATED).entity(newUser).build(); - } catch (Exception e) { - // TODO: handle exception - return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); - } - // add pet - //return Response.ok().entity("SUCCESS").build(); + public Response connection(ConnexionDTO dto) { + + // user contient juste email + password + try { + UserResponseDTO response = userService.seConnecter(dto); + return Response.ok(response).build(); + } catch (Exception e) { + return Response.status(401).entity("Email ou mot de passe incorrect").build(); + } + } } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java index d4fcf5a0..86e9d12f 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java @@ -1,5 +1,60 @@ package fr.istic.taa.jaxrs.service; +import org.mindrot.jbcrypt.BCrypt; + +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.Client; +import fr.istic.taa.jaxrs.dto.*; + public class ClientService { + + private ClientDao clientDao; + private UserDao userDao; + + // Injection par constructeur + public ClientService(ClientDao clientDao, UserDao userDao) { + this.clientDao = clientDao; + this.userDao = userDao; + } + + + //1-Methode metier S'inscrire + public UserResponseDTO inscription(InscriptionDTO dto) throws Exception { + + if (this.userDao.findByEmailNamedQuery(dto.getEmail()) != null) { + throw new Exception("Email déjà utilisé"); + } + + Client client = new Client(); + + client.setNom(dto.getNom()); + client.setPrenom(dto.getPrenom()); + client.setEmail(dto.getEmail()); + client.setTel(dto.getTel()); + client.setDate_naissance(dto.getDate_naissance()); + client.setStatut_user(true); + + String hashed = BCrypt.hashpw(dto.getPassword(), BCrypt.gensalt()); + client.setPassword(hashed); + + this.clientDao.save(client); // Appel simple au DAO + + // Mapper vers DTO de réponse + UserResponseDTO response = new UserResponseDTO(); + response.setId(client.getUserId()); + response.setNom(client.getNom()); + response.setPrenom(client.getPrenom()); + response.setEmail(client.getEmail()); + response.setTel(client.getTel()); + response.setStatut_user(client.isStatut_user()); + response.setDate_naissance(client.getDate_naissance()); + + response.setRole("CLIENT"); //### A revoir + + return response; + } + + //2-Methode metier Se Connecter (voir User) } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java b/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java new file mode 100644 index 00000000..052c867c --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java @@ -0,0 +1,30 @@ +package fr.istic.taa.jaxrs.service; + +import org.mindrot.jbcrypt.BCrypt; + +import fr.istic.taa.jaxrs.dao.*; +import fr.istic.taa.jaxrs.domain.*; + +public class ManagerService { + + private ManagerDao managerDao; + private UserDao userDao; + + public ManagerService(ManagerDao managerDao, UserDao userDao) { + this.managerDao = managerDao; + this.userDao = userDao; + } + + //1-Methode metier inscrire Manager + public void inscriptionManager(Manager manager) throws Exception { + + if (this.userDao.findByEmailNamedQuery(manager.getEmail()) != null) { + throw new Exception("Email déjà utilisé"); + } + String tempPassword = manager.getNom()+("123"); // ex: "Kouassi123" + manager.setPassword(BCrypt.hashpw(tempPassword, BCrypt.gensalt())); + this.managerDao.save(manager); // Appel simple au DAO + } + + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/service/UserService.java b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java index f0139e57..1393ac7a 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/UserService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java @@ -2,43 +2,88 @@ import org.mindrot.jbcrypt.BCrypt; import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.*; import fr.istic.taa.jaxrs.domain.User; +import fr.istic.taa.jaxrs.dto.ConnexionDTO; +import fr.istic.taa.jaxrs.dto.PasswordDTO; +import fr.istic.taa.jaxrs.dto.UserResponseDTO; public class UserService { + + private UserDao userDao; + + // Injection par constructeur + public UserService(UserDao userDao) { + this.userDao = userDao; + } - //1-proposition d'implementation pour methode s'inscrire - public void inscription(User user) throws Exception { - UserDao userDao = new UserDao(); - - if (userDao.findByEmail(user.getEmail()) != null) { - throw new Exception("Email déjà utilisé"); + + //1-Methode seConnecter + public UserResponseDTO seConnecter(ConnexionDTO dto) { + // 1. On demande au DAO de nous donner l'utilisateur par son email + User user = userDao.findByEmailNamedQuery(dto.getEmail()); + + if (user == null) { + throw new RuntimeException("Utilisateur non trouvé"); } - String hashed = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()); - user.setPassword(hashed); - userDao.save(user); // Appel simple au DAO + + // 2. C'est ICI qu'on utilise la fonction de comparaison + // On ne fait JAMAIS "if (motDePasseSaisi == user.getPassword())" + boolean match = BCrypt.checkpw(dto.getPassword(), user.getPassword()); + + if (!match) { + throw new RuntimeException("Mot de passe incorrect"); + } + + + String role = null; + if (user instanceof Client) { + role = "CLIENT"; + } else if (user instanceof Manager) { + role = "MANAGER"; + } else if (user instanceof Admin) { + role = "ADMIN"; + } + + + // Mapper vers DTO de réponse + UserResponseDTO response = new UserResponseDTO(); + response.setId(user.getUserId()); + response.setNom(user.getNom()); + response.setPrenom(user.getPrenom()); + response.setEmail(user.getEmail()); + response.setTel(user.getTel()); + response.setStatut_user(user.isStatut_user()); + response.setDate_naissance(user.getDate_naissance()); + + response.setRole(role); //### A revoir + + return response; // Connexion réussie } + //Déconnexion Invalide la session en cours ou supprime le token (pas besoin du DAO ici en général). - //2-proposition d'implementation pour methode seConnecter -// public User seConnecter(String email, String motDePasseSaisi) { -// // 1. On demande au DAO de nous donner l'utilisateur par son email -// User user = userReferenceDao.findByEmail(email); -// -// if (user == null) { -// throw new RuntimeException("Utilisateur non trouvé"); -// } -// -// // 2. C'est ICI qu'on utilise la fonction de comparaison -// // On ne fait JAMAIS "if (motDePasseSaisi == user.getPassword())" -// boolean match = BCrypt.checkpw(motDePasseSaisi, user.getPassword()); -// -// if (!match) { -// throw new RuntimeException("Mot de passe incorrect"); -// } -// -// return user; // Connexion réussie -// } + + + //2- Modifier MDP + public void changerMdp(Long user_id, PasswordDTO dto) throws Exception { - //3-Déconnexion Invalide la session en cours ou supprime le token (pas besoin du DAO ici en général). + User user = userDao.findOne(user_id); + + if (user == null) { + throw new RuntimeException("Utilisateur non trouvé"); + } + boolean match = BCrypt.checkpw(dto.getOldPassword(), user.getPassword()); + + if (!match) { + throw new RuntimeException("Ancien mot de passe incorrect"); + } + + String hashed = BCrypt.hashpw(dto.getNewPassword(), BCrypt.gensalt()); + user.setPassword(hashed); + + this.userDao.update(user); + + } } From 62a80cc8797620df051f6c61dff0ffb59e5275da Mon Sep 17 00:00:00 2001 From: KADI JOLIE Date: Sun, 26 Apr 2026 14:56:53 +0200 Subject: [PATCH 03/18] ajout backend concerts --- .DS_Store | Bin 0 -> 6148 bytes pom.xml | 8 + src/.DS_Store | Bin 0 -> 6148 bytes src/main/.DS_Store | Bin 0 -> 6148 bytes .../fr/istic/taa/jaxrs/TestApplication.java | 25 +- .../fr/istic/taa/jaxrs/dao/ClientDao.java | 29 - .../java/fr/istic/taa/jaxrs/dao/EventDao.java | 26 + .../fr/istic/taa/jaxrs/dao/TicketDao.java | 30 +- .../java/fr/istic/taa/jaxrs/dao/UserDao.java | 62 +- .../java/fr/istic/taa/jaxrs/domain/Admin.java | 23 +- .../fr/istic/taa/jaxrs/domain/Client.java | 24 +- .../java/fr/istic/taa/jaxrs/domain/Event.java | 191 +- .../fr/istic/taa/jaxrs/domain/Manager.java | 26 +- .../java/fr/istic/taa/jaxrs/domain/Pet.java | 44 - .../fr/istic/taa/jaxrs/domain/Ticket.java | 76 +- .../fr/istic/taa/jaxrs/domain/TicketId.java | 2 +- .../java/fr/istic/taa/jaxrs/domain/User.java | 96 +- .../jaxrs/domain/enumeration/NiveauAdmin.java | 6 + .../taa/jaxrs/domain/enumeration/Role.java | 6 + .../domain/enumeration/StatutTicket.java | 7 + .../istic/taa/jaxrs/dto/AchatTicketDto.java | 58 + .../{ConnexionDTO.java => ConnexionDto.java} | 2 +- ...ionDTO.java => EnregistrerManagerDto.java} | 44 +- .../java/fr/istic/taa/jaxrs/dto/EventDto.java | 87 + ...onseDTO.java => InscriptionClientDto.java} | 63 +- .../istic/taa/jaxrs/dto/ModificationDTO.java | 40 - .../{PasswordDTO.java => PasswordDto.java} | 2 +- .../istic/taa/jaxrs/dto/UserResponseDto.java | 126 + .../java/fr/istic/taa/jaxrs/jpa/JpaTest.java | 124 +- .../istic/taa/jaxrs/rest/AdminResource.java | 50 + .../istic/taa/jaxrs/rest/ClientResource.java | 68 + .../istic/taa/jaxrs/rest/ClientRessource.java | 49 - .../istic/taa/jaxrs/rest/EventResource.java | 74 + .../istic/taa/jaxrs/rest/ManagerResource.java | 60 + .../fr/istic/taa/jaxrs/rest/PetResource.java | 38 - .../istic/taa/jaxrs/rest/SwaggerResource.java | 34 + .../istic/taa/jaxrs/rest/TicketResource.java | 87 + .../fr/istic/taa/jaxrs/rest/UserResource.java | 105 +- .../istic/taa/jaxrs/service/AdminService.java | 41 +- .../taa/jaxrs/service/ClientService.java | 19 +- .../istic/taa/jaxrs/service/EventService.java | 59 +- .../taa/jaxrs/service/ManagerService.java | 40 +- .../taa/jaxrs/service/TicketService.java | 66 + .../istic/taa/jaxrs/service/UserService.java | 60 +- src/main/resources/META-INF/persistence.xml | 2 +- src/main/webapp/.DS_Store | Bin 0 -> 6148 bytes src/main/webapp/swagger/.agignore | 1 + src/main/webapp/swagger/.browserslistrc | 29 + .../swagger/.claude/SKILL_USAGE_EXAMPLE.md | 565 + .../webapp/swagger/.claude/skills/README.md | 151 + .../swagger/.claude/skills/add-oas-support.md | 2333 ++ src/main/webapp/swagger/.commitlintrc.json | 25 + src/main/webapp/swagger/.dockerignore | 8 + src/main/webapp/swagger/.editorconfig | 10 + src/main/webapp/swagger/.eslintignore | 3 + src/main/webapp/swagger/.eslintrc.js | 78 + src/main/webapp/swagger/.gitattributes | 4 + .../.github/ISSUE_TEMPLATE/Bug_report.md | 73 + .../.github/ISSUE_TEMPLATE/Feature_request.md | 42 + .../swagger/.github/ISSUE_TEMPLATE/Support.md | 46 + .../webapp/swagger/.github/dependabot.yaml | 35 + src/main/webapp/swagger/.github/lock.yml | 15 + .../swagger/.github/pull_request_template.md | 55 + .../swagger/.github/workflows/codeql.yml | 63 + .../.github/workflows/dependabot-merge.yml | 40 + .../workflows/docker-build-push-unstable.yml | 52 + .../.github/workflows/docker-build-push.yml | 77 + .../.github/workflows/docker-image-check.yml | 23 + .../swagger/.github/workflows/nodejs.yml | 86 + .../workflows/release-swagger-ui-dist.yml | 61 + .../release-swagger-ui-packagist.yml | 21 + .../workflows/release-swagger-ui-react.yml | 61 + .../.github/workflows/release-swagger-ui.yml | 95 + src/main/webapp/swagger/.gitignore | 29 + src/main/webapp/swagger/.husky/commit-msg | 1 + src/main/webapp/swagger/.husky/pre-commit | 1 + src/main/webapp/swagger/.lintstagedrc | 4 + src/main/webapp/swagger/.npmignore | 16 + src/main/webapp/swagger/.npmrc | 1 + src/main/webapp/swagger/.nvmrc | 1 + src/main/webapp/swagger/.prettierrc.yaml | 5 + src/main/webapp/swagger/.releaserc | 26 + src/main/webapp/swagger/CLAUDE.md | 1072 + src/main/webapp/swagger/Dockerfile | 51 + src/main/webapp/swagger/LICENSE | 202 + src/main/webapp/swagger/NOTICE | 2 + src/main/webapp/swagger/README.md | 118 + src/main/webapp/swagger/SECURITY.md | 23 + src/main/webapp/swagger/babel.config.js | 140 + src/main/webapp/swagger/composer.json | 40 + src/main/webapp/swagger/config/.eslintrc | 8 + .../config/jest/jest.artifact.config.js | 9 + .../swagger/config/jest/jest.unit.config.js | 24 + src/main/webapp/swagger/cypress.config.js | 19 + .../dev-helpers/dev-helper-initializer.js | 33 + .../webapp/swagger/dev-helpers/index.html | 21 + .../swagger/dev-helpers/oauth2-redirect.html | 6 + .../swagger/dev-helpers/oauth2-redirect.js | 69 + src/main/webapp/swagger/dev-helpers/style.css | 19 + .../webapp/swagger/dist/favicon-16x16.png | Bin 0 -> 665 bytes .../webapp/swagger/dist/favicon-32x32.png | Bin 0 -> 628 bytes src/main/webapp/swagger/dist/index.css | 16 + src/main/webapp/swagger/dist/index.html | 19 + .../webapp/swagger/dist/oauth2-redirect.html | 6 + .../webapp/swagger/dist/oauth2-redirect.js | 1 + .../swagger/dist/swagger-initializer.js | 20 + .../webapp/swagger/dist/swagger-ui-bundle.js | 2 + .../swagger/dist/swagger-ui-es-bundle-core.js | 3 + .../swagger/dist/swagger-ui-es-bundle.js | 2 + .../dist/swagger-ui-standalone-preset.js | 2 + src/main/webapp/swagger/dist/swagger-ui.css | 3 + src/main/webapp/swagger/dist/swagger-ui.js | 2 + .../swagger/docker/configurator/helpers.js | 13 + .../swagger/docker/configurator/index.js | 52 + .../swagger/docker/configurator/oauth.js | 55 + .../swagger/docker/configurator/translator.js | 111 + .../swagger/docker/configurator/variables.js | 125 + src/main/webapp/swagger/docker/cors.conf | 14 + .../swagger/docker/default.conf.template | 43 + .../docker-entrypoint.d/40-swagger-ui.sh | 52 + src/main/webapp/swagger/docker/embedding.conf | 5 + .../flavors/swagger-ui-react/README.md | 227 + .../flavors/swagger-ui-react/index.jsx | 180 + .../release/create-manifest.js | 9 + .../flavors/swagger-ui-react/release/run.sh | 42 + .../swagger-ui-react/release/template.json | 53 + src/main/webapp/swagger/package-lock.json | 28378 ++++++++++++++++ src/main/webapp/swagger/package.json | 214 + .../webapp/swagger/release/.release-it.json | 28 + .../release/check-for-breaking-changes.sh | 14 + .../webapp/swagger/release/get-changelog.sh | 5 + src/main/webapp/swagger/snapcraft.yaml | 28 + src/main/webapp/swagger/src/.eslintrc | 10 + .../swagger/src/core/assets/rolling-load.svg | 1 + .../swagger/src/core/components/app.jsx | 30 + .../src/core/components/auth/api-key-auth.jsx | 93 + .../src/core/components/auth/auth-item.jsx | 60 + .../components/auth/authorization-popup.jsx | 59 + .../core/components/auth/authorize-btn.jsx | 30 + .../auth/authorize-operation-btn.jsx | 35 + .../src/core/components/auth/auths.jsx | 124 + .../src/core/components/auth/basic-auth.jsx | 110 + .../src/core/components/auth/error.jsx | 24 + .../src/core/components/auth/oauth2.jsx | 283 + .../swagger/src/core/components/clear.jsx | 25 + .../swagger/src/core/components/contact.jsx | 44 + .../src/core/components/content-type.jsx | 64 + .../core/components/copy-to-clipboard-btn.jsx | 29 + .../swagger/src/core/components/curl.jsx | 38 + .../swagger/src/core/components/debug.jsx | 50 + .../swagger/src/core/components/deep-link.jsx | 20 + .../swagger/src/core/components/errors.jsx | 132 + .../swagger/src/core/components/example.jsx | 43 + .../examples-select-value-retainer.jsx | 254 + .../src/core/components/examples-select.jsx | 139 + .../swagger/src/core/components/execute.jsx | 103 + .../swagger/src/core/components/footer.jsx | 9 + .../swagger/src/core/components/headers.jsx | 58 + .../swagger/src/core/components/info.jsx | 155 + .../src/core/components/initialized-input.jsx | 36 + .../src/core/components/jump-to-path.jsx | 9 + .../src/core/components/layout-utils.jsx | 265 + .../src/core/components/layouts/base.jsx | 154 + .../src/core/components/layouts/xpane.jsx | 73 + .../swagger/src/core/components/license.jsx | 40 + .../src/core/components/live-response.jsx | 133 + .../components/online-validator-badge.jsx | 120 + .../src/core/components/openapi-version.jsx | 15 + .../components/operation-extension-row.jsx | 17 + .../core/components/operation-extensions.jsx | 35 + .../components/operation-summary-method.jsx | 25 + .../components/operation-summary-path.jsx | 54 + .../src/core/components/operation-summary.jsx | 108 + .../src/core/components/operation-tag.jsx | 121 + .../swagger/src/core/components/operation.jsx | 257 + .../src/core/components/operations.jsx | 99 + .../swagger/src/core/components/overview.jsx | 119 + .../src/core/components/param-body.jsx | 156 + .../core/components/parameter-extension.jsx | 12 + .../components/parameter-include-empty.jsx | 59 + .../src/core/components/parameter-row.jsx | 438 + .../src/core/components/parameters/index.js | 1 + .../core/components/parameters/parameters.jsx | 286 + .../swagger/src/core/components/property.jsx | 17 + .../src/core/components/providers/README.md | 6 + .../core/components/providers/markdown.jsx | 72 + .../src/core/components/response-body.jsx | 170 + .../core/components/response-extension.jsx | 12 + .../swagger/src/core/components/response.jsx | 276 + .../swagger/src/core/components/responses.jsx | 170 + .../src/core/components/svg-assets.jsx | 48 + .../src/core/components/system-wrapper.jsx | 0 .../src/core/components/try-it-out-button.jsx | 41 + .../core/components/version-pragma-filter.jsx | 54 + .../src/core/components/version-stamp.jsx | 12 + .../swagger/src/core/config/defaults.js | 101 + .../config/factorization/inline-plugin.js | 10 + .../src/core/config/factorization/system.js | 44 + .../webapp/swagger/src/core/config/index.js | 12 + .../webapp/swagger/src/core/config/merge.js | 58 + .../swagger/src/core/config/sources/query.js | 28 + .../src/core/config/sources/runtime.js | 18 + .../swagger/src/core/config/sources/url.js | 38 + .../src/core/config/type-cast/index.js | 24 + .../src/core/config/type-cast/mappings.js | 139 + .../config/type-cast/type-casters/array.js | 7 + .../config/type-cast/type-casters/boolean.js | 11 + .../config/type-cast/type-casters/dom-node.js | 7 + .../config/type-cast/type-casters/filter.js | 11 + .../config/type-cast/type-casters/function.js | 7 + .../type-cast/type-casters/nullable-array.js | 6 + .../type-casters/nullable-function.js | 7 + .../type-cast/type-casters/nullable-string.js | 7 + .../config/type-cast/type-casters/number.js | 9 + .../config/type-cast/type-casters/object.js | 9 + .../config/type-cast/type-casters/sorter.js | 7 + .../config/type-cast/type-casters/string.js | 6 + .../type-casters/syntax-highlight.js | 14 + .../type-casters/undefined-string.js | 7 + .../core/containers/OperationContainer.jsx | 271 + .../src/core/containers/authorize-btn.jsx | 31 + .../swagger/src/core/containers/filter.jsx | 44 + .../swagger/src/core/containers/info.jsx | 34 + src/main/webapp/swagger/src/core/index.js | 174 + .../swagger/src/core/oauth2-authorize.js | 137 + .../swagger/src/core/plugins/auth/actions.js | 286 + .../auth/components/lock-auth-icon.jsx | 27 + .../auth/components/unlock-auth-icon.jsx | 27 + .../auth/configs-extensions/wrap-actions.js | 19 + .../swagger/src/core/plugins/auth/index.js | 94 + .../swagger/src/core/plugins/auth/reducers.js | 77 + .../src/core/plugins/auth/selectors.js | 121 + .../auth/spec-extensions/wrap-actions.js | 10 + .../src/core/plugins/auth/wrap-actions.js | 66 + .../src/core/plugins/configs/actions.js | 58 + .../swagger/src/core/plugins/configs/fn.js | 12 + .../swagger/src/core/plugins/configs/index.js | 16 + .../src/core/plugins/configs/reducers.js | 20 + .../src/core/plugins/configs/selectors.js | 4 + .../src/core/plugins/deep-linking/README.md | 1 + .../src/core/plugins/deep-linking/helpers.js | 7 + .../src/core/plugins/deep-linking/index.js | 24 + .../src/core/plugins/deep-linking/layout.js | 209 + .../deep-linking/operation-tag-wrapper.jsx | 25 + .../deep-linking/operation-wrapper.jsx | 27 + .../src/core/plugins/download-url/index.js | 126 + .../swagger/src/core/plugins/err/actions.js | 60 + .../plugins/err/error-transformers/README.md | 31 + .../plugins/err/error-transformers/hook.js | 38 + .../transformers/not-of-type.js | 29 + .../transformers/parameter-oneof.js | 59 + .../swagger/src/core/plugins/err/index.js | 15 + .../swagger/src/core/plugins/err/reducers.js | 100 + .../swagger/src/core/plugins/err/selectors.js | 15 + .../swagger/src/core/plugins/filter/index.js | 9 + .../src/core/plugins/filter/opsFilter.js | 3 + .../plugins/icons/components/arrow-down.jsx | 28 + .../plugins/icons/components/arrow-up.jsx | 28 + .../core/plugins/icons/components/arrow.jsx | 28 + .../core/plugins/icons/components/close.jsx | 28 + .../core/plugins/icons/components/copy.jsx | 34 + .../core/plugins/icons/components/lock.jsx | 28 + .../core/plugins/icons/components/unlock.jsx | 28 + .../swagger/src/core/plugins/icons/index.js | 24 + .../fn/api/encoderAPI.js | 20 + .../fn/api/formatAPI.js | 20 + .../fn/api/mediaTypeAPI.js | 27 + .../fn/api/optionAPI.js | 17 + .../fn/class/EncoderRegistry.js | 33 + .../fn/class/FormatRegistry.js | 65 + .../fn/class/MediaTypeRegistry.js | 27 + .../fn/class/OptionRegistry.js | 16 + .../fn/class/Registry.js | 24 + .../fn/core/constants.js | 6 + .../fn/core/example.js | 57 + .../fn/core/merge.js | 83 + .../fn/core/predicates.js | 16 + .../fn/core/random.js | 46 + .../fn/core/type.js | 156 + .../fn/core/utils.js | 23 + .../fn/encoders/7bit.js | 6 + .../fn/encoders/8bit.js | 6 + .../fn/encoders/base16.js | 6 + .../fn/encoders/base32.js | 34 + .../fn/encoders/base64.js | 6 + .../fn/encoders/base64url.js | 6 + .../fn/encoders/binary.js | 6 + .../fn/encoders/quoted-printable.js | 38 + .../fn/generators/date-time.js | 6 + .../fn/generators/date.js | 6 + .../fn/generators/double.js | 6 + .../fn/generators/duration.js | 6 + .../fn/generators/email.js | 6 + .../fn/generators/float.js | 6 + .../fn/generators/hostname.js | 6 + .../fn/generators/idn-email.js | 6 + .../fn/generators/idn-hostname.js | 6 + .../fn/generators/int32.js | 6 + .../fn/generators/int64.js | 6 + .../fn/generators/ipv4.js | 6 + .../fn/generators/ipv6.js | 6 + .../fn/generators/iri-reference.js | 6 + .../fn/generators/iri.js | 6 + .../fn/generators/json-pointer.js | 6 + .../fn/generators/media-types/application.js | 17 + .../fn/generators/media-types/audio.js | 10 + .../fn/generators/media-types/image.js | 10 + .../fn/generators/media-types/text.js | 17 + .../fn/generators/media-types/video.js | 10 + .../fn/generators/password.js | 6 + .../fn/generators/regex.js | 6 + .../fn/generators/relative-json-pointer.js | 6 + .../fn/generators/time.js | 6 + .../fn/generators/uri-reference.js | 6 + .../fn/generators/uri-template.js | 7 + .../fn/generators/uri.js | 6 + .../fn/generators/uuid.js | 6 + .../fn/get-json-sample-schema.js | 36 + .../fn/get-sample-schema.js | 39 + .../fn/get-xml-sample-schema.js | 35 + .../fn/get-yaml-sample-schema.js | 34 + .../json-schema-2020-12-samples/fn/index.js | 16 + .../json-schema-2020-12-samples/fn/main.js | 562 + .../fn/types/array.js | 52 + .../fn/types/boolean.js | 9 + .../fn/types/index.js | 30 + .../fn/types/integer.js | 43 + .../fn/types/null.js | 9 + .../fn/types/number.js | 65 + .../fn/types/object.js | 9 + .../fn/types/string.js | 80 + .../json-schema-2020-12-samples/index.js | 51 + .../components/Accordion/Accordion.jsx | 45 + .../components/Accordion/_accordion.scss | 33 + .../ExpandDeepButton/ExpandDeepButton.jsx | 31 + .../ExpandDeepButton/_expand-deep-button.scss | 10 + .../components/JSONSchema/JSONSchema.jsx | 227 + .../components/JSONSchema/_json-schema.scss | 34 + .../components/JSONViewer/JSONViewer.jsx | 153 + .../components/JSONViewer/_json-viewer.scss | 11 + .../json-schema-2020-12/components/_all.scss | 4 + .../components/_mixins.scss | 82 + .../components/icons/ChevronRight.jsx | 17 + .../components/keywords/$anchor.jsx | 27 + .../components/keywords/$comment.jsx | 27 + .../components/keywords/$defs.jsx | 93 + .../components/keywords/$dynamicAnchor.jsx | 27 + .../components/keywords/$dynamicRef.jsx | 27 + .../components/keywords/$id.jsx | 27 + .../components/keywords/$ref.jsx | 27 + .../components/keywords/$schema.jsx | 27 + .../keywords/$vocabulary/$vocabulary.jsx | 66 + .../keywords/$vocabulary/_$vocabulary.scss | 17 + .../keywords/AdditionalProperties.jsx | 55 + .../components/keywords/AllOf.jsx | 105 + .../components/keywords/AnyOf.jsx | 105 + .../components/keywords/Const/Const.jsx | 28 + .../components/keywords/Const/_const.scss | 11 + .../keywords/Constraint/Constraint.jsx | 38 + .../keywords/Constraint/_constraint.scss | 16 + .../components/keywords/Contains.jsx | 35 + .../components/keywords/ContentSchema.jsx | 39 + .../components/keywords/Default/Default.jsx | 28 + .../components/keywords/Default/_default.scss | 11 + .../DependentRequired/DependentRequired.jsx | 37 + .../_dependent-required.scss | 12 + .../components/keywords/DependentSchemas.jsx | 97 + .../components/keywords/Deprecated.jsx | 22 + .../keywords/Description/Description.jsx | 24 + .../keywords/Description/_description.scss | 9 + .../components/keywords/Else.jsx | 35 + .../components/keywords/Enum/Enum.jsx | 27 + .../components/keywords/Enum/_enum.scss | 11 + .../components/keywords/Examples/Examples.jsx | 30 + .../keywords/Examples/_examples.scss | 11 + .../ExtensionKeywords/ExtensionKeywords.jsx | 103 + .../_extension-keywords.scss | 11 + .../components/keywords/If.jsx | 35 + .../components/keywords/Items.jsx | 35 + .../components/keywords/Not.jsx | 35 + .../components/keywords/OneOf.jsx | 105 + .../PatternProperties/PatternProperties.jsx | 41 + .../_pattern-properties.scss | 21 + .../components/keywords/PrefixItems.jsx | 105 + .../keywords/Properties/Properties.jsx | 61 + .../keywords/Properties/_properties.scss | 24 + .../components/keywords/PropertyNames.jsx | 38 + .../components/keywords/ReadOnly.jsx | 22 + .../components/keywords/Then.jsx | 35 + .../components/keywords/Title/Title.jsx | 24 + .../components/keywords/Title/_title.scss | 26 + .../components/keywords/Type.jsx | 27 + .../components/keywords/UnevaluatedItems.jsx | 39 + .../keywords/UnevaluatedProperties.jsx | 39 + .../components/keywords/WriteOnly.jsx | 22 + .../components/keywords/_all.scss | 43 + .../plugins/json-schema-2020-12/context.js | 14 + .../core/plugins/json-schema-2020-12/enum.js | 10 + .../core/plugins/json-schema-2020-12/fn.js | 527 + .../core/plugins/json-schema-2020-12/hoc.jsx | 296 + .../core/plugins/json-schema-2020-12/hooks.js | 144 + .../core/plugins/json-schema-2020-12/index.js | 153 + .../plugins/json-schema-2020-12/prop-types.js | 10 + .../fn/get-json-sample-schema.js | 32 + .../fn/get-sample-schema.js | 31 + .../fn/get-xml-sample-schema.js | 31 + .../fn/get-yaml-sample-schema.js | 34 + .../plugins/json-schema-5-samples/fn/index.js | 653 + .../plugins/json-schema-5-samples/index.js | 56 + .../json-schema-5/components/array-model.jsx | 80 + .../json-schema-5/components/enum-model.jsx | 19 + .../components/json-schema-components.jsx | 441 + .../components/model-collapse.jsx | 99 + .../components/model-example.jsx | 160 + .../components/model-extensions.jsx | 28 + .../components/model-wrapper.jsx | 44 + .../json-schema-5/components/model.jsx | 136 + .../json-schema-5/components/models.jsx | 139 + .../json-schema-5/components/object-model.jsx | 340 + .../components/primitive-model.jsx | 137 + .../json-schema-5/components/schemes.jsx | 53 + .../json-schema-5/containers/schemes.jsx | 30 + .../src/core/plugins/json-schema-5/fn.js | 51 + .../src/core/plugins/json-schema-5/index.js | 41 + .../src/core/plugins/layout/actions.js | 39 + .../swagger/src/core/plugins/layout/index.js | 19 + .../src/core/plugins/layout/reducers.js | 32 + .../src/core/plugins/layout/selectors.js | 24 + .../layout/spec-extensions/wrap-selector.js | 22 + .../swagger/src/core/plugins/logs/index.js | 28 + .../swagger/src/core/plugins/oas3/actions.js | 99 + .../oas3/auth-extensions/wrap-selectors.js | 92 + .../oas3/components/auth/http-auth.jsx | 157 + .../plugins/oas3/components/callbacks.jsx | 51 + .../src/core/plugins/oas3/components/index.js | 19 + .../oas3/components/operation-link.jsx | 43 + .../oas3/components/operation-servers.jsx | 102 + .../oas3/components/request-body-editor.jsx | 103 + .../plugins/oas3/components/request-body.jsx | 338 + .../oas3/components/servers-container.jsx | 33 + .../core/plugins/oas3/components/servers.jsx | 153 + .../swagger/src/core/plugins/oas3/fn.js | 35 + .../swagger/src/core/plugins/oas3/helpers.jsx | 48 + .../swagger/src/core/plugins/oas3/index.js | 39 + .../swagger/src/core/plugins/oas3/reducers.js | 111 + .../src/core/plugins/oas3/selectors.js | 308 + .../plugins/oas3/spec-extensions/selectors.js | 100 + .../oas3/spec-extensions/wrap-selectors.js | 71 + .../oas3/wrap-components/auth/auth-item.jsx | 25 + .../plugins/oas3/wrap-components/index.js | 15 + .../wrap-components/json-schema-string.jsx | 27 + .../plugins/oas3/wrap-components/markdown.jsx | 45 + .../plugins/oas3/wrap-components/model.jsx | 40 + .../wrap-components/online-validator-badge.js | 5 + .../oas3/wrap-components/openapi-version.jsx | 7 + .../src/core/plugins/oas31/after-load.js | 72 + .../oas31/auth-extensions/wrap-selectors.js | 28 + .../core/plugins/oas31/components/_all.scss | 2 + .../plugins/oas31/components/auth/auths.jsx | 186 + .../oas31/components/auth/mutual-tls-auth.jsx | 32 + .../core/plugins/oas31/components/contact.jsx | 43 + .../core/plugins/oas31/components/info.jsx | 99 + .../oas31/components/json-schema-dialect.jsx | 60 + .../core/plugins/oas31/components/license.jsx | 38 + .../oas31/components/model/_model.scss | 23 + .../plugins/oas31/components/model/model.jsx | 54 + .../oas31/components/models/_models.scss | 11 + .../oas31/components/models/models.jsx | 141 + .../components/version-pragma-filter.jsx | 73 + .../plugins/oas31/components/webhooks.jsx | 49 + .../swagger/src/core/plugins/oas31/fn.js | 124 + .../swagger/src/core/plugins/oas31/index.js | 166 + .../components/keywords/Description.jsx | 27 + .../keywords/Discriminator/Discriminator.jsx | 118 + .../Discriminator/DiscriminatorMapping.jsx | 32 + .../components/keywords/Example.jsx | 28 + .../components/keywords/ExternalDocs.jsx | 143 + .../components/keywords/OpenAPIExtensions.jsx | 33 + .../components/keywords/Properties.jsx | 60 + .../components/keywords/Xml.jsx | 162 + .../json-schema-2020-12-extensions/fn.js | 57 + .../wrap-components/keywords/Description.jsx | 9 + .../wrap-components/keywords/Examples.jsx | 31 + .../wrap-components/keywords/Properties.jsx | 9 + .../core/plugins/oas31/oas3-extensions/fn.js | 46 + .../src/core/plugins/oas31/selectors.js | 26 + .../oas31/spec-extensions/selectors.js | 198 + .../oas31/spec-extensions/wrap-selectors.js | 18 + .../oas31/wrap-components/auth/auth-item.jsx | 22 + .../plugins/oas31/wrap-components/auths.jsx | 17 + .../plugins/oas31/wrap-components/contact.jsx | 15 + .../plugins/oas31/wrap-components/info.jsx | 15 + .../plugins/oas31/wrap-components/license.jsx | 15 + .../plugins/oas31/wrap-components/model.jsx | 57 + .../plugins/oas31/wrap-components/models.jsx | 54 + .../wrap-components/version-pragma-filter.jsx | 16 + .../src/core/plugins/oas32/after-load.js | 58 + .../components/version-pragma-filter.jsx | 80 + .../swagger/src/core/plugins/oas32/fn.js | 124 + .../swagger/src/core/plugins/oas32/index.js | 130 + .../components/keywords/Description.jsx | 27 + .../components/keywords/Properties.jsx | 60 + .../json-schema-2020-12-extensions/fn.js | 20 + .../wrap-components/keywords/Description.jsx | 9 + .../wrap-components/keywords/Examples.jsx | 31 + .../wrap-components/keywords/Properties.jsx | 9 + .../core/plugins/oas32/oas3-extensions/fn.js | 46 + .../src/core/plugins/oas32/selectors.js | 24 + .../oas32/spec-extensions/selectors.js | 86 + .../oas32/spec-extensions/wrap-selectors.js | 27 + .../plugins/oas32/wrap-components/contact.jsx | 13 + .../plugins/oas32/wrap-components/info.jsx | 15 + .../plugins/oas32/wrap-components/license.jsx | 13 + .../plugins/oas32/wrap-components/model.jsx | 57 + .../plugins/oas32/wrap-components/models.jsx | 54 + .../oas32/wrap-components/openapi-version.jsx | 11 + .../wrap-components/version-pragma-filter.jsx | 16 + .../src/core/plugins/on-complete/index.js | 28 + .../src/core/plugins/request-snippets/fn.js | 169 + .../core/plugins/request-snippets/index.js | 21 + .../request-snippets/request-snippets.jsx | 163 + .../plugins/request-snippets/selectors.js | 45 + .../safe-render/components/error-boundary.jsx | 52 + .../safe-render/components/fallback.jsx | 13 + .../src/core/plugins/safe-render/fn.jsx | 32 + .../src/core/plugins/safe-render/index.js | 42 + .../swagger/src/core/plugins/spec/actions.js | 531 + .../swagger/src/core/plugins/spec/index.js | 20 + .../swagger/src/core/plugins/spec/reducers.js | 176 + .../src/core/plugins/spec/selectors.js | 576 + .../src/core/plugins/spec/wrap-actions.js | 39 + .../swagger-client/configs-wrap-actions.js | 6 + .../src/core/plugins/swagger-client/index.js | 54 + .../plugins/syntax-highlighting/after-load.js | 25 + .../components/HighlightCode.jsx | 107 + .../components/PlainTextViewer.jsx | 17 + .../components/SyntaxHighlighter.jsx | 42 + .../core/plugins/syntax-highlighting/index.js | 34 + .../syntax-highlighting/root-injects.js | 22 + .../wrap-components/SyntaxHighlighter.jsx | 31 + .../swagger/src/core/plugins/util/index.js | 11 + .../src/core/plugins/versions/after-load.js | 19 + .../src/core/plugins/versions/index.js | 10 + .../src/core/plugins/view-legacy/index.js | 25 + .../core/plugins/view-legacy/root-injects.jsx | 12 + .../swagger/src/core/plugins/view/fn.js | 1 + .../swagger/src/core/plugins/view/index.js | 34 + .../src/core/plugins/view/root-injects.jsx | 118 + .../swagger/src/core/presets/apis/index.js | 20 + .../swagger/src/core/presets/base/index.js | 55 + .../base/plugins/core-components/index.js | 130 + .../base/plugins/form-components/index.js | 10 + src/main/webapp/swagger/src/core/system.js | 511 + .../src/core/utils/create-html-ready-id.js | 10 + .../src/core/utils/get-parameter-schema.js | 94 + .../webapp/swagger/src/core/utils/index.js | 845 + .../swagger/src/core/utils/jsonParse.js | 15 + .../webapp/swagger/src/core/utils/memoizeN.js | 48 + src/main/webapp/swagger/src/core/utils/url.js | 79 + src/main/webapp/swagger/src/core/window.js | 30 + src/main/webapp/swagger/src/index.js | 3 + .../components/StandaloneLayout.jsx | 40 + .../plugins/stadalone-layout/index.js | 12 + .../plugins/top-bar/assets/lightbulb-off.svg | 1 + .../plugins/top-bar/assets/lightbulb.svg | 1 + .../plugins/top-bar/assets/logo_small.svg | 60 + .../top-bar/components/DarkModeToggle.jsx | 47 + .../plugins/top-bar/components/Logo.jsx | 9 + .../plugins/top-bar/components/TopBar.jsx | 183 + .../src/standalone/plugins/top-bar/index.js | 12 + .../standalone/presets/standalone/index.js | 19 + .../webapp/swagger/src/style/_authorize.scss | 96 + .../webapp/swagger/src/style/_buttons.scss | 199 + .../webapp/swagger/src/style/_dark-mode.scss | 742 + .../webapp/swagger/src/style/_errors.scss | 72 + src/main/webapp/swagger/src/style/_form.scss | 214 + .../swagger/src/style/_information.scss | 99 + .../webapp/swagger/src/style/_layout.scss | 949 + .../webapp/swagger/src/style/_markdown.scss | 34 + .../webapp/swagger/src/style/_mixins.scss | 159 + src/main/webapp/swagger/src/style/_modal.scss | 95 + .../webapp/swagger/src/style/_models.scss | 330 + .../webapp/swagger/src/style/_servers.scss | 66 + .../swagger/src/style/_split-pane-mode.scss | 3 + src/main/webapp/swagger/src/style/_table.scss | 191 + .../webapp/swagger/src/style/_topbar.scss | 126 + src/main/webapp/swagger/src/style/_type.scss | 21 + .../webapp/swagger/src/style/_variables.scss | 231 + src/main/webapp/swagger/src/style/main.scss | 31 + src/main/webapp/swagger/stylelint.config.js | 11 + .../swagger-ui-dist-package/.npmignore | 2 + .../swagger/swagger-ui-dist-package/.npmrc | 1 + .../swagger/swagger-ui-dist-package/README.md | 40 + .../swagger-ui-dist-package/absolute-path.js | 14 + .../swagger/swagger-ui-dist-package/deploy.sh | 25 + .../swagger/swagger-ui-dist-package/index.js | 17 + .../swagger-ui-dist-package/package.json | 20 + .../webapp/swagger/webpack/_config-builder.js | 170 + src/main/webapp/swagger/webpack/_helpers.js | 27 + src/main/webapp/swagger/webpack/bundle.js | 68 + src/main/webapp/swagger/webpack/core.js | 29 + src/main/webapp/swagger/webpack/dev-e2e.js | 79 + src/main/webapp/swagger/webpack/dev.js | 127 + .../webapp/swagger/webpack/es-bundle-core.js | 90 + src/main/webapp/swagger/webpack/es-bundle.js | 54 + src/main/webapp/swagger/webpack/standalone.js | 30 + .../webapp/swagger/webpack/stylesheets.js | 82 + 607 files changed, 69107 insertions(+), 642 deletions(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store create mode 100644 src/main/.DS_Store delete mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/Pet.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/enumeration/NiveauAdmin.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/enumeration/Role.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/domain/enumeration/StatutTicket.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/AchatTicketDto.java rename src/main/java/fr/istic/taa/jaxrs/dto/{ConnexionDTO.java => ConnexionDto.java} (92%) rename src/main/java/fr/istic/taa/jaxrs/dto/{InscriptionDTO.java => EnregistrerManagerDto.java} (76%) create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/EventDto.java rename src/main/java/fr/istic/taa/jaxrs/dto/{UserResponseDTO.java => InscriptionClientDto.java} (66%) delete mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java rename src/main/java/fr/istic/taa/jaxrs/dto/{PasswordDTO.java => PasswordDto.java} (93%) create mode 100644 src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDto.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/AdminResource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/ClientResource.java delete mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/EventResource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/ManagerResource.java delete mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/PetResource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/SwaggerResource.java create mode 100644 src/main/java/fr/istic/taa/jaxrs/rest/TicketResource.java create mode 100644 src/main/webapp/.DS_Store create mode 100644 src/main/webapp/swagger/.agignore create mode 100644 src/main/webapp/swagger/.browserslistrc create mode 100644 src/main/webapp/swagger/.claude/SKILL_USAGE_EXAMPLE.md create mode 100644 src/main/webapp/swagger/.claude/skills/README.md create mode 100644 src/main/webapp/swagger/.claude/skills/add-oas-support.md create mode 100644 src/main/webapp/swagger/.commitlintrc.json create mode 100644 src/main/webapp/swagger/.dockerignore create mode 100644 src/main/webapp/swagger/.editorconfig create mode 100644 src/main/webapp/swagger/.eslintignore create mode 100644 src/main/webapp/swagger/.eslintrc.js create mode 100644 src/main/webapp/swagger/.gitattributes create mode 100644 src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Feature_request.md create mode 100644 src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Support.md create mode 100644 src/main/webapp/swagger/.github/dependabot.yaml create mode 100644 src/main/webapp/swagger/.github/lock.yml create mode 100644 src/main/webapp/swagger/.github/pull_request_template.md create mode 100644 src/main/webapp/swagger/.github/workflows/codeql.yml create mode 100644 src/main/webapp/swagger/.github/workflows/dependabot-merge.yml create mode 100644 src/main/webapp/swagger/.github/workflows/docker-build-push-unstable.yml create mode 100644 src/main/webapp/swagger/.github/workflows/docker-build-push.yml create mode 100644 src/main/webapp/swagger/.github/workflows/docker-image-check.yml create mode 100644 src/main/webapp/swagger/.github/workflows/nodejs.yml create mode 100644 src/main/webapp/swagger/.github/workflows/release-swagger-ui-dist.yml create mode 100644 src/main/webapp/swagger/.github/workflows/release-swagger-ui-packagist.yml create mode 100644 src/main/webapp/swagger/.github/workflows/release-swagger-ui-react.yml create mode 100644 src/main/webapp/swagger/.github/workflows/release-swagger-ui.yml create mode 100644 src/main/webapp/swagger/.gitignore create mode 100755 src/main/webapp/swagger/.husky/commit-msg create mode 100755 src/main/webapp/swagger/.husky/pre-commit create mode 100644 src/main/webapp/swagger/.lintstagedrc create mode 100644 src/main/webapp/swagger/.npmignore create mode 100644 src/main/webapp/swagger/.npmrc create mode 100644 src/main/webapp/swagger/.nvmrc create mode 100644 src/main/webapp/swagger/.prettierrc.yaml create mode 100644 src/main/webapp/swagger/.releaserc create mode 100644 src/main/webapp/swagger/CLAUDE.md create mode 100644 src/main/webapp/swagger/Dockerfile create mode 100644 src/main/webapp/swagger/LICENSE create mode 100644 src/main/webapp/swagger/NOTICE create mode 100644 src/main/webapp/swagger/README.md create mode 100644 src/main/webapp/swagger/SECURITY.md create mode 100644 src/main/webapp/swagger/babel.config.js create mode 100644 src/main/webapp/swagger/composer.json create mode 100644 src/main/webapp/swagger/config/.eslintrc create mode 100644 src/main/webapp/swagger/config/jest/jest.artifact.config.js create mode 100644 src/main/webapp/swagger/config/jest/jest.unit.config.js create mode 100644 src/main/webapp/swagger/cypress.config.js create mode 100644 src/main/webapp/swagger/dev-helpers/dev-helper-initializer.js create mode 100644 src/main/webapp/swagger/dev-helpers/index.html create mode 100644 src/main/webapp/swagger/dev-helpers/oauth2-redirect.html create mode 100644 src/main/webapp/swagger/dev-helpers/oauth2-redirect.js create mode 100644 src/main/webapp/swagger/dev-helpers/style.css create mode 100644 src/main/webapp/swagger/dist/favicon-16x16.png create mode 100644 src/main/webapp/swagger/dist/favicon-32x32.png create mode 100644 src/main/webapp/swagger/dist/index.css create mode 100644 src/main/webapp/swagger/dist/index.html create mode 100644 src/main/webapp/swagger/dist/oauth2-redirect.html create mode 100644 src/main/webapp/swagger/dist/oauth2-redirect.js create mode 100644 src/main/webapp/swagger/dist/swagger-initializer.js create mode 100644 src/main/webapp/swagger/dist/swagger-ui-bundle.js create mode 100644 src/main/webapp/swagger/dist/swagger-ui-es-bundle-core.js create mode 100644 src/main/webapp/swagger/dist/swagger-ui-es-bundle.js create mode 100644 src/main/webapp/swagger/dist/swagger-ui-standalone-preset.js create mode 100644 src/main/webapp/swagger/dist/swagger-ui.css create mode 100644 src/main/webapp/swagger/dist/swagger-ui.js create mode 100644 src/main/webapp/swagger/docker/configurator/helpers.js create mode 100755 src/main/webapp/swagger/docker/configurator/index.js create mode 100644 src/main/webapp/swagger/docker/configurator/oauth.js create mode 100644 src/main/webapp/swagger/docker/configurator/translator.js create mode 100644 src/main/webapp/swagger/docker/configurator/variables.js create mode 100644 src/main/webapp/swagger/docker/cors.conf create mode 100644 src/main/webapp/swagger/docker/default.conf.template create mode 100755 src/main/webapp/swagger/docker/docker-entrypoint.d/40-swagger-ui.sh create mode 100644 src/main/webapp/swagger/docker/embedding.conf create mode 100644 src/main/webapp/swagger/flavors/swagger-ui-react/README.md create mode 100644 src/main/webapp/swagger/flavors/swagger-ui-react/index.jsx create mode 100644 src/main/webapp/swagger/flavors/swagger-ui-react/release/create-manifest.js create mode 100755 src/main/webapp/swagger/flavors/swagger-ui-react/release/run.sh create mode 100644 src/main/webapp/swagger/flavors/swagger-ui-react/release/template.json create mode 100644 src/main/webapp/swagger/package-lock.json create mode 100644 src/main/webapp/swagger/package.json create mode 100644 src/main/webapp/swagger/release/.release-it.json create mode 100755 src/main/webapp/swagger/release/check-for-breaking-changes.sh create mode 100755 src/main/webapp/swagger/release/get-changelog.sh create mode 100644 src/main/webapp/swagger/snapcraft.yaml create mode 100644 src/main/webapp/swagger/src/.eslintrc create mode 100644 src/main/webapp/swagger/src/core/assets/rolling-load.svg create mode 100644 src/main/webapp/swagger/src/core/components/app.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/api-key-auth.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/auth-item.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/authorization-popup.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/authorize-btn.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/authorize-operation-btn.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/auths.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/basic-auth.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/error.jsx create mode 100644 src/main/webapp/swagger/src/core/components/auth/oauth2.jsx create mode 100644 src/main/webapp/swagger/src/core/components/clear.jsx create mode 100644 src/main/webapp/swagger/src/core/components/contact.jsx create mode 100644 src/main/webapp/swagger/src/core/components/content-type.jsx create mode 100644 src/main/webapp/swagger/src/core/components/copy-to-clipboard-btn.jsx create mode 100644 src/main/webapp/swagger/src/core/components/curl.jsx create mode 100644 src/main/webapp/swagger/src/core/components/debug.jsx create mode 100644 src/main/webapp/swagger/src/core/components/deep-link.jsx create mode 100644 src/main/webapp/swagger/src/core/components/errors.jsx create mode 100644 src/main/webapp/swagger/src/core/components/example.jsx create mode 100644 src/main/webapp/swagger/src/core/components/examples-select-value-retainer.jsx create mode 100644 src/main/webapp/swagger/src/core/components/examples-select.jsx create mode 100644 src/main/webapp/swagger/src/core/components/execute.jsx create mode 100644 src/main/webapp/swagger/src/core/components/footer.jsx create mode 100644 src/main/webapp/swagger/src/core/components/headers.jsx create mode 100644 src/main/webapp/swagger/src/core/components/info.jsx create mode 100644 src/main/webapp/swagger/src/core/components/initialized-input.jsx create mode 100644 src/main/webapp/swagger/src/core/components/jump-to-path.jsx create mode 100644 src/main/webapp/swagger/src/core/components/layout-utils.jsx create mode 100644 src/main/webapp/swagger/src/core/components/layouts/base.jsx create mode 100644 src/main/webapp/swagger/src/core/components/layouts/xpane.jsx create mode 100644 src/main/webapp/swagger/src/core/components/license.jsx create mode 100644 src/main/webapp/swagger/src/core/components/live-response.jsx create mode 100644 src/main/webapp/swagger/src/core/components/online-validator-badge.jsx create mode 100644 src/main/webapp/swagger/src/core/components/openapi-version.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-extension-row.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-extensions.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-summary-method.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-summary-path.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-summary.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation-tag.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operation.jsx create mode 100644 src/main/webapp/swagger/src/core/components/operations.jsx create mode 100644 src/main/webapp/swagger/src/core/components/overview.jsx create mode 100644 src/main/webapp/swagger/src/core/components/param-body.jsx create mode 100644 src/main/webapp/swagger/src/core/components/parameter-extension.jsx create mode 100644 src/main/webapp/swagger/src/core/components/parameter-include-empty.jsx create mode 100644 src/main/webapp/swagger/src/core/components/parameter-row.jsx create mode 100644 src/main/webapp/swagger/src/core/components/parameters/index.js create mode 100644 src/main/webapp/swagger/src/core/components/parameters/parameters.jsx create mode 100644 src/main/webapp/swagger/src/core/components/property.jsx create mode 100644 src/main/webapp/swagger/src/core/components/providers/README.md create mode 100644 src/main/webapp/swagger/src/core/components/providers/markdown.jsx create mode 100644 src/main/webapp/swagger/src/core/components/response-body.jsx create mode 100644 src/main/webapp/swagger/src/core/components/response-extension.jsx create mode 100644 src/main/webapp/swagger/src/core/components/response.jsx create mode 100644 src/main/webapp/swagger/src/core/components/responses.jsx create mode 100644 src/main/webapp/swagger/src/core/components/svg-assets.jsx create mode 100644 src/main/webapp/swagger/src/core/components/system-wrapper.jsx create mode 100644 src/main/webapp/swagger/src/core/components/try-it-out-button.jsx create mode 100644 src/main/webapp/swagger/src/core/components/version-pragma-filter.jsx create mode 100644 src/main/webapp/swagger/src/core/components/version-stamp.jsx create mode 100644 src/main/webapp/swagger/src/core/config/defaults.js create mode 100644 src/main/webapp/swagger/src/core/config/factorization/inline-plugin.js create mode 100644 src/main/webapp/swagger/src/core/config/factorization/system.js create mode 100644 src/main/webapp/swagger/src/core/config/index.js create mode 100644 src/main/webapp/swagger/src/core/config/merge.js create mode 100644 src/main/webapp/swagger/src/core/config/sources/query.js create mode 100644 src/main/webapp/swagger/src/core/config/sources/runtime.js create mode 100644 src/main/webapp/swagger/src/core/config/sources/url.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/index.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/mappings.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/array.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/boolean.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/dom-node.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/filter.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/function.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/nullable-array.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/nullable-function.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/nullable-string.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/number.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/object.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/sorter.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/string.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/syntax-highlight.js create mode 100644 src/main/webapp/swagger/src/core/config/type-cast/type-casters/undefined-string.js create mode 100644 src/main/webapp/swagger/src/core/containers/OperationContainer.jsx create mode 100644 src/main/webapp/swagger/src/core/containers/authorize-btn.jsx create mode 100644 src/main/webapp/swagger/src/core/containers/filter.jsx create mode 100644 src/main/webapp/swagger/src/core/containers/info.jsx create mode 100644 src/main/webapp/swagger/src/core/index.js create mode 100644 src/main/webapp/swagger/src/core/oauth2-authorize.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/components/lock-auth-icon.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/components/unlock-auth-icon.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/configs-extensions/wrap-actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/spec-extensions/wrap-actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/auth/wrap-actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/configs/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/configs/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/configs/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/configs/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/configs/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/README.md create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/helpers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/layout.js create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/operation-tag-wrapper.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/deep-linking/operation-wrapper.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/download-url/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/error-transformers/README.md create mode 100644 src/main/webapp/swagger/src/core/plugins/err/error-transformers/hook.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/error-transformers/transformers/not-of-type.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/error-transformers/transformers/parameter-oneof.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/err/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/filter/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/filter/opsFilter.js create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/arrow-down.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/arrow-up.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/arrow.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/close.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/copy.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/lock.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/components/unlock.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/icons/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/api/encoderAPI.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/api/formatAPI.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/api/mediaTypeAPI.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/api/optionAPI.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/class/EncoderRegistry.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/class/FormatRegistry.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/class/MediaTypeRegistry.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/class/OptionRegistry.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/class/Registry.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/constants.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/example.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/merge.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/predicates.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/random.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/type.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/core/utils.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/7bit.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/8bit.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/base16.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/base32.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/base64.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/base64url.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/binary.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/encoders/quoted-printable.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/date-time.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/date.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/double.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/duration.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/email.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/float.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/hostname.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/idn-email.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/idn-hostname.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/int32.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/int64.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/ipv4.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/ipv6.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/iri-reference.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/iri.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/json-pointer.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/application.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/audio.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/image.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/text.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/video.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/password.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/regex.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/relative-json-pointer.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/time.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/uri-reference.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/uri-template.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/uri.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/generators/uuid.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/get-json-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/get-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/get-xml-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/get-yaml-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/main.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/array.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/boolean.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/integer.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/null.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/number.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/object.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/fn/types/string.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12-samples/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/Accordion/Accordion.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/Accordion/_accordion.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/ExpandDeepButton/ExpandDeepButton.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/ExpandDeepButton/_expand-deep-button.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/JSONSchema/JSONSchema.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/JSONSchema/_json-schema.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/JSONViewer/JSONViewer.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/JSONViewer/_json-viewer.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/_all.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/_mixins.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/icons/ChevronRight.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$anchor.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$comment.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$defs.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$dynamicAnchor.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$dynamicRef.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$id.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$ref.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$schema.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$vocabulary/$vocabulary.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/$vocabulary/_$vocabulary.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/AdditionalProperties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/AllOf.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/AnyOf.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Const/Const.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Const/_const.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Constraint/Constraint.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Constraint/_constraint.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Contains.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/ContentSchema.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Default/Default.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Default/_default.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/DependentRequired.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/_dependent-required.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/DependentSchemas.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Deprecated.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Description/Description.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Description/_description.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Else.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Enum/Enum.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Enum/_enum.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Examples/Examples.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Examples/_examples.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/ExtensionKeywords/ExtensionKeywords.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/ExtensionKeywords/_extension-keywords.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/If.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Items.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Not.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/OneOf.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/PatternProperties/PatternProperties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/PatternProperties/_pattern-properties.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/PrefixItems.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Properties/Properties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/PropertyNames.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/ReadOnly.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Then.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Title/Title.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Title/_title.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/Type.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/UnevaluatedItems.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/UnevaluatedProperties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/WriteOnly.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/components/keywords/_all.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/context.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/enum.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/hoc.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/hooks.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-2020-12/prop-types.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/fn/get-json-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/fn/get-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/fn/get-xml-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/fn/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5-samples/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/array-model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/enum-model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/json-schema-components.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/model-collapse.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/model-example.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/model-extensions.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/model-wrapper.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/models.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/object-model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/primitive-model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/components/schemes.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/containers/schemes.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/json-schema-5/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/layout/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/layout/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/layout/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/layout/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/layout/spec-extensions/wrap-selector.js create mode 100644 src/main/webapp/swagger/src/core/plugins/logs/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/auth-extensions/wrap-selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/auth/http-auth.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/callbacks.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/operation-link.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/operation-servers.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/request-body-editor.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/request-body.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/servers-container.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/components/servers.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/helpers.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/spec-extensions/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/spec-extensions/wrap-selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/auth/auth-item.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/json-schema-string.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/markdown.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/online-validator-badge.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas3/wrap-components/openapi-version.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/after-load.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/auth-extensions/wrap-selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/_all.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/auth/auths.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/contact.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/info.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/json-schema-dialect.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/license.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/model/_model.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/model/model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/models/_models.scss create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/models/models.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/version-pragma-filter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/components/webhooks.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Description.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Discriminator/Discriminator.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Discriminator/DiscriminatorMapping.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Example.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/ExternalDocs.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/OpenAPIExtensions.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Properties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Xml.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Description.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Examples.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Properties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/oas3-extensions/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/spec-extensions/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/spec-extensions/wrap-selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/auth/auth-item.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/auths.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/contact.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/info.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/license.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/models.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas31/wrap-components/version-pragma-filter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/after-load.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/components/version-pragma-filter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/components/keywords/Description.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/components/keywords/Properties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/wrap-components/keywords/Description.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/wrap-components/keywords/Examples.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/json-schema-2020-12-extensions/wrap-components/keywords/Properties.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/oas3-extensions/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/spec-extensions/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/spec-extensions/wrap-selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/contact.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/info.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/license.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/model.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/models.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/openapi-version.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/oas32/wrap-components/version-pragma-filter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/on-complete/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/request-snippets/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/request-snippets/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/request-snippets/request-snippets.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/request-snippets/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/safe-render/components/error-boundary.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/safe-render/components/fallback.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/safe-render/fn.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/safe-render/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/spec/actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/spec/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/spec/reducers.js create mode 100644 src/main/webapp/swagger/src/core/plugins/spec/selectors.js create mode 100644 src/main/webapp/swagger/src/core/plugins/spec/wrap-actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/swagger-client/configs-wrap-actions.js create mode 100644 src/main/webapp/swagger/src/core/plugins/swagger-client/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/after-load.js create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/components/HighlightCode.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/components/PlainTextViewer.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/components/SyntaxHighlighter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/root-injects.js create mode 100644 src/main/webapp/swagger/src/core/plugins/syntax-highlighting/wrap-components/SyntaxHighlighter.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/util/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/versions/after-load.js create mode 100644 src/main/webapp/swagger/src/core/plugins/versions/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/view-legacy/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/view-legacy/root-injects.jsx create mode 100644 src/main/webapp/swagger/src/core/plugins/view/fn.js create mode 100644 src/main/webapp/swagger/src/core/plugins/view/index.js create mode 100644 src/main/webapp/swagger/src/core/plugins/view/root-injects.jsx create mode 100644 src/main/webapp/swagger/src/core/presets/apis/index.js create mode 100644 src/main/webapp/swagger/src/core/presets/base/index.js create mode 100644 src/main/webapp/swagger/src/core/presets/base/plugins/core-components/index.js create mode 100644 src/main/webapp/swagger/src/core/presets/base/plugins/form-components/index.js create mode 100644 src/main/webapp/swagger/src/core/system.js create mode 100644 src/main/webapp/swagger/src/core/utils/create-html-ready-id.js create mode 100644 src/main/webapp/swagger/src/core/utils/get-parameter-schema.js create mode 100644 src/main/webapp/swagger/src/core/utils/index.js create mode 100644 src/main/webapp/swagger/src/core/utils/jsonParse.js create mode 100644 src/main/webapp/swagger/src/core/utils/memoizeN.js create mode 100644 src/main/webapp/swagger/src/core/utils/url.js create mode 100644 src/main/webapp/swagger/src/core/window.js create mode 100644 src/main/webapp/swagger/src/index.js create mode 100644 src/main/webapp/swagger/src/standalone/plugins/stadalone-layout/components/StandaloneLayout.jsx create mode 100644 src/main/webapp/swagger/src/standalone/plugins/stadalone-layout/index.js create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/assets/lightbulb-off.svg create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/assets/lightbulb.svg create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/assets/logo_small.svg create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/components/DarkModeToggle.jsx create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/components/Logo.jsx create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/components/TopBar.jsx create mode 100644 src/main/webapp/swagger/src/standalone/plugins/top-bar/index.js create mode 100644 src/main/webapp/swagger/src/standalone/presets/standalone/index.js create mode 100644 src/main/webapp/swagger/src/style/_authorize.scss create mode 100644 src/main/webapp/swagger/src/style/_buttons.scss create mode 100644 src/main/webapp/swagger/src/style/_dark-mode.scss create mode 100644 src/main/webapp/swagger/src/style/_errors.scss create mode 100644 src/main/webapp/swagger/src/style/_form.scss create mode 100644 src/main/webapp/swagger/src/style/_information.scss create mode 100644 src/main/webapp/swagger/src/style/_layout.scss create mode 100644 src/main/webapp/swagger/src/style/_markdown.scss create mode 100644 src/main/webapp/swagger/src/style/_mixins.scss create mode 100644 src/main/webapp/swagger/src/style/_modal.scss create mode 100644 src/main/webapp/swagger/src/style/_models.scss create mode 100644 src/main/webapp/swagger/src/style/_servers.scss create mode 100644 src/main/webapp/swagger/src/style/_split-pane-mode.scss create mode 100644 src/main/webapp/swagger/src/style/_table.scss create mode 100644 src/main/webapp/swagger/src/style/_topbar.scss create mode 100644 src/main/webapp/swagger/src/style/_type.scss create mode 100644 src/main/webapp/swagger/src/style/_variables.scss create mode 100644 src/main/webapp/swagger/src/style/main.scss create mode 100644 src/main/webapp/swagger/stylelint.config.js create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/.npmignore create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/.npmrc create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/README.md create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/absolute-path.js create mode 100755 src/main/webapp/swagger/swagger-ui-dist-package/deploy.sh create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/index.js create mode 100644 src/main/webapp/swagger/swagger-ui-dist-package/package.json create mode 100644 src/main/webapp/swagger/webpack/_config-builder.js create mode 100644 src/main/webapp/swagger/webpack/_helpers.js create mode 100644 src/main/webapp/swagger/webpack/bundle.js create mode 100644 src/main/webapp/swagger/webpack/core.js create mode 100644 src/main/webapp/swagger/webpack/dev-e2e.js create mode 100644 src/main/webapp/swagger/webpack/dev.js create mode 100644 src/main/webapp/swagger/webpack/es-bundle-core.js create mode 100644 src/main/webapp/swagger/webpack/es-bundle.js create mode 100644 src/main/webapp/swagger/webpack/standalone.js create mode 100644 src/main/webapp/swagger/webpack/stylesheets.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ba23ab656066bdfcef94e6739c025d07c12abe5b GIT binary patch literal 6148 zcmeHK&2G~`5S~p!<4}HbXr*3|EO8B?0ksw4l7{raflH0x04UgX)I_-65GM^%6v=0J z2VQ|IPr|!!f^T*=QoKneP6*K*Y3JLYnc1ChZLgPzL}wbei0VY-p)gi%LTwNp=dvax z({l?bIL7lto<)g_(B^s_bwR7SuhDF)2tJY-*D@tlu5L# zhtaEHf7Yw-Jd^1p9H#xTau~*an7n;GOk+9g$Y~m9$~VvhUd^lZ>U;C~6ac56ML;KO;Ygz`3I2w!tOvvtV+*49009Q{D@<-r^@2 zT%2S7?R{sjRX)(X#$vejwy!Y + org.webjars + swagger-ui + 5.0.0 + + + + mysql mysql-connector-java diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bfd612cac2ec9e881a2dfff0a5da2e57ed2deb44 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O0-BN@c6nYGJE!rryh?f}a!K)EHsMN$14W`-BA9E;$ob`o#5?@DW zcDDupPJ&38f!S{}JF{WF4Lcde822Z!%b3j=6QGEtDh%HUuA_dDlChKlIqq?i%G)TF z5j^9DB>$fQJUff^S;!KWeLBBGSlfD2q7qs7Mfqr8&iN%8q{(R9Y`*eR*;-kxh>EC* z>)>AI!8jaGMt(TF#HTYU(`Y^qqw}PfckT5fnT^9F>kU;v68FI6>LSTvnfr2*#Um9P z=mk*~)vjHiPIvcq8jjm)&l=8j-*p>K%WcnQRk5+TeQ?@+Nc)+5($sVKE|shqoWnCr z7Wq5|!z`8A9oXjnb3a02fEXYKmXQH-*NNIPCPz6D1H{0u7{L3%0Y&r-78=#n0fTA* z04*>pfw}ti2XxQ?=ou_Df(3-@P(U5ZO^d-z=fHJ1tb4}4(5S;1S8s-W%$vFCP`GJ4 zxTD+|_cYQ-3=jh!8Nl8T#K!u6{B!@WoM<2hh=Ju~fLooQ<3nzywtmSHYpnx%1B!xv ng~mk)OjIcbUo6FSP$gh@a02KVEHr`zgnk4R4Kxq~f6Bl+fzMRA literal 0 HcmV?d00001 diff --git a/src/main/.DS_Store b/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..22a2f5e295a058a66cf064d799b49a7be8c9fe1d GIT binary patch literal 6148 zcmeHK!A{#i5S zSH6Vbp>K9Kl@eNxQ9(1(?3bV{VO_Ajka4q+u|^f5 zQp`S}!F;TG{a9>Tl>>K@Zqq@Ym80F=JJnceuCA?n>)wX!{(I1+Gtk*}#`Ds@4bk))0qF0*S*baEU=XYD1lgZn6Z`wh) zw?AzMllNiR4)((R>D2dLZS8#c)cu+ND)g1%gcMG`krxhUa1CQ_|CjNw$aV1z{#ni} zR!|ra284m-GT?3@Z)3U3%4))ZFz^Hz;QJwfGDZ$-i{|P;V@d#E6K*50&96T&UXIw`X<=5Z@4SD`3Zc&NaHlZq@#D+~w&^9-!m zZj0alqkq@`^GVVZ284lU#eixa#)lnj$-S))Hpg#m0R0MO;ker3pA;D8DMl> getClasses() { final Set> clazzes = new HashSet>(); clazzes.add(OpenApiResource.class); - clazzes.add(PetResource.class); clazzes.add(UserResource.class); - clazzes.add(ClientRessource.class); -// clazzes.add(AcceptHeaderOpenApiResource.class); + clazzes.add(ClientResource.class); + clazzes.add(AdminResource.class); + clazzes.add(ManagerResource.class); + clazzes.add(EventResource.class); + clazzes.add(TicketResource.class); + clazzes.add(SwaggerResource.class); - return clazzes; } diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java index 0f04434f..7a8b31af 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/ClientDao.java @@ -10,35 +10,6 @@ public ClientDao() { this.setClazz(Client.class); } - -////Requete avec JPQL -// public Client findByEmail(String email) { -// -// String query_jpql = "SELECT c FROM Client c WHERE c.email = :emailValue"; -// try { -// return entityManager.createQuery(query_jpql, Client.class) -// .setParameter("emailValue", email) -// .getSingleResult(); -// } catch (NoResultException e) { -// // Retourne null si aucun utilisateur n'est trouvé -// return null; -// } -// } -// - - - //Requete NamedQuery -// public Client findByIdNamedQuery(Long id) { -// try { -// return entityManager -// .createNamedQuery("Client.findById", Client.class) -// .setParameter("user_id", id) -// .getSingleResult(); -// } catch (NoResultException e) { -// // Retourne null si aucun utilisateur n'est trouvé -// return null; -// } -// } // // // Criteria Query : On construit la requête avec du code Java. // public List findAllUser() { diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java index f5afa551..4f199e0d 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/EventDao.java @@ -1,7 +1,12 @@ package fr.istic.taa.jaxrs.dao; +import java.time.LocalDate; +import java.util.List; + import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.Event; +import fr.istic.taa.jaxrs.domain.Manager; +import fr.istic.taa.jaxrs.domain.Ticket; public class EventDao extends AbstractJpaDao { @@ -9,6 +14,27 @@ public EventDao() { this.setClazz(Event.class); } + //Requete NamedQuery + public List findByDateEventNamedQuery(LocalDate date) { + + return entityManager + .createNamedQuery("Event.findByDateEvent", Event.class) + .setParameter("dateConcert", date) + .getResultList(); + } + + + // Requête JPQL + public List findByManagerId(Long managerId) { + String query_jpql = "SELECT e FROM Event e WHERE e.manager.userId = :manager_id"; + + return entityManager + .createQuery(query_jpql, Event.class) + .setParameter("manager_id", managerId) + .getResultList(); + + } + // findAll() // // searchByCriteria(String keyword, Date date, String lieu) (pour la recherche). diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java index a58da7d9..28acd0d6 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/TicketDao.java @@ -1,13 +1,9 @@ package fr.istic.taa.jaxrs.dao; -import java.util.Collections; import java.util.List; - import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.Ticket; import fr.istic.taa.jaxrs.domain.TicketId; -import fr.istic.taa.jaxrs.domain.User; -import jakarta.persistence.NoResultException; public class TicketDao extends AbstractJpaDao { @@ -16,30 +12,22 @@ public TicketDao() { } //Requete NamedQuery - public List findByUserIdNamedQuery(Long id) { - try { - return entityManager - .createNamedQuery("Ticket.findByUserId", Ticket.class) - .setParameter("user_id", id) - .getResultList(); - } catch (NoResultException e) { - // Retourne liste vide si aucun utilisateur n'est trouvé - return Collections.emptyList(); - } + public List findByClientIdNamedQuery(Long id) { + + return entityManager + .createNamedQuery("Ticket.findByClientId", Ticket.class) + .setParameter("client_id", id) + .getResultList(); } - // Requête pour voir qui vient à un concert + // Requête JPQL public List findByEventId(Long eid) { String query_jpql = "SELECT t FROM Ticket t WHERE t.event.eventId = :event_id"; - try { + return entityManager .createQuery(query_jpql, Ticket.class) .setParameter("event_id", eid) - .getResultList(); - - } catch (Exception e) { - return Collections.emptyList(); - } + .getResultList(); } // save(Ticket t) diff --git a/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java index 1a7e2765..4183e6ee 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java +++ b/src/main/java/fr/istic/taa/jaxrs/dao/UserDao.java @@ -1,8 +1,14 @@ package fr.istic.taa.jaxrs.dao; +import java.util.List; + import fr.istic.taa.jaxrs.dao.generic.AbstractJpaDao; import fr.istic.taa.jaxrs.domain.*; +import fr.istic.taa.jaxrs.dto.UserResponseDto; import jakarta.persistence.*; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; public class UserDao extends AbstractJpaDao { @@ -13,42 +19,28 @@ public UserDao() { //Requete NamedQuery public User findByEmailNamedQuery(String email) { - try { - return entityManager - .createNamedQuery("User.findByEmail", User.class) - .setParameter("emailValue", email) - .getSingleResult(); - } catch (NoResultException e) { - // Retourne null si aucun utilisateur n'est trouvé - return null; - } + try { + return entityManager + .createNamedQuery("User.findByEmail", User.class) + .setParameter("emailValue", email) + .getSingleResult(); + } catch (NoResultException e) { + return null; // aucun utilisateur trouvé + } } -// //Requete NamedQuery -// public User findByIdNamedQuery(Long id) { -// try { -// return entityManager -// .createNamedQuery("User.findById", User.class) -// .setParameter("user_id", id) -// .getSingleResult(); -// } catch (NoResultException e) { -// // Retourne null si aucun utilisateur n'est trouvé -// return null; -// } -// } -// -// // Criteria Query : On construit la requête avec du code Java. -// public List findAllUser() { -// -// CriteriaBuilder cb = entityManager.getCriteriaBuilder(); -// -// CriteriaQuery cq = cb.createQuery(User.class); -// -// Root userRoot = cq.from(User.class); -// -// cq.select(userRoot); -// -// return entityManager.createQuery(cq).getResultList(); -// } + // Criteria Query : On construit la requête avec du code Java. + public List findAllUser() { + + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery cq = cb.createQuery(User.class); + + Root userRoot = cq.from(User.class); + + cq.select(userRoot); + + return entityManager.createQuery(cq).getResultList(); + } } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java b/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java index 4b3192ca..d2a75165 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Admin.java @@ -3,20 +3,38 @@ import java.io.Serializable; import java.util.List; +import com.fasterxml.jackson.annotation.JsonManagedReference; + +import fr.istic.taa.jaxrs.domain.enumeration.NiveauAdmin; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.OneToMany; @Entity public class Admin extends User implements Serializable { + @Enumerated(EnumType.STRING) + private NiveauAdmin admin_niveau; + + @OneToMany(mappedBy = "admin", cascade = CascadeType.PERSIST) + @JsonManagedReference private List events; //GETTERS - SETTERS + + + public NiveauAdmin getAdmin_niveau() { + return admin_niveau; + } + public void setAdmin_niveau(NiveauAdmin admin_niveau) { + this.admin_niveau = admin_niveau; + } + - @OneToMany(mappedBy = "admin", cascade = CascadeType.PERSIST) public List getEvents() { return events; } @@ -28,8 +46,9 @@ public void setEvents(List events) { @Override public String toString() { return "Admin [events=" + events + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" - + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + email + ", telephone=" + telephone + ", date_naissance=" + date_naissance + ", password=" + password + ", statut_User=" + statut_user + "]"; } + } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Client.java b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java index 43ea15d6..dda83da8 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Client.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Client.java @@ -3,22 +3,31 @@ import java.io.Serializable; import java.util.List; +import com.fasterxml.jackson.annotation.JsonManagedReference; + import jakarta.persistence.*; @Entity -////Requete NamedQuery -//@NamedQuery( -// name = "Client.findById", -// query = "SELECT c FROM Client c WHERE c.userId = :user_id" -// ) public class Client extends User implements Serializable{ + private boolean client_newsletter = false; + + @OneToMany(mappedBy = "client", cascade = CascadeType.PERSIST) + @JsonManagedReference private List tickets; //GETTERS - SETTERS - @OneToMany(mappedBy = "client", cascade = CascadeType.PERSIST) + + public boolean isClient_newsletter() { + return client_newsletter; + } + public void setClient_newsletter(boolean client_newsletter) { + this.client_newsletter = client_newsletter; + } + + public List getTickets() { return tickets; } @@ -30,7 +39,8 @@ public void setTickets(List tickets) { @Override public String toString() { return "Client [tickets=" + tickets + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" - + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + email + ", telephone=" + telephone + ", date_naissance=" + date_naissance + ", password=" + password + ", statut_User=" + statut_user + "]"; } + } \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Event.java b/src/main/java/fr/istic/taa/jaxrs/domain/Event.java index 6f7b3d57..5a3bdb7e 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Event.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Event.java @@ -1,151 +1,196 @@ package fr.istic.taa.jaxrs.domain; import java.io.Serializable; +import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + import jakarta.persistence.*; @Entity +//Requete NamedQuery +@NamedQuery( + name = "Event.findByDateEvent", + query = "SELECT e FROM Event e WHERE e.date_concert = :dateConcert" + ) public class Event implements Serializable { + @Id + @GeneratedValue private long eventId; private String nom; private String description; private String artiste; private String lieu; - private LocalDate dateConcert; + private int dureeConcert; private String genreMusical; - private int nbPlaceDispo; - private String dureeConcert; - private String statut; - private LocalDate dateValidation; - private String commentairesAdmin; + private int nb_place_disponible; + private boolean statut_concert = true; + + @Column(precision = 8, scale = 2) + private BigDecimal prix_ticket; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate date_concert; + + @ManyToOne + @JoinColumn(name = "managerId", nullable = false) + @JsonBackReference private Manager manager; + + @ManyToOne + @JoinColumn(name = "adminId", nullable = false) + @JsonBackReference private Admin admin; + + + @OneToMany(mappedBy = "event", cascade = CascadeType.PERSIST) + @JsonManagedReference private List tickets; - + //GETTERS - SETTERS - @Id - @GeneratedValue - public long getEventId() { + + public long getEventId() { return eventId; } public void setEventId(long eventId) { this.eventId = eventId; } - @ManyToOne - public Manager getManager() { - return manager; - } - public void setManager(Manager manager) { - this.manager = manager; - } - - @ManyToOne - public Admin getAdmin() { - return admin; - } - public void setAdmin(Admin admin) { - this.admin = admin; - } - - @OneToMany(mappedBy = "event", cascade = CascadeType.PERSIST) - public List getTickets() { - return tickets; - } - public void setTickets(List tickets) { - this.tickets = tickets; - } - - public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } - + + public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } - + + public String getArtiste() { return artiste; } public void setArtiste(String artiste) { this.artiste = artiste; } - + + public String getLieu() { return lieu; } public void setLieu(String lieu) { this.lieu = lieu; } - - public LocalDate getDateConcert() { - return dateConcert; + + + public int getDureeConcert() { + return dureeConcert; } - public void setDateConcert(LocalDate dateConcert) { - this.dateConcert = dateConcert; + public void setDureeConcert(int dureeConcert) { + this.dureeConcert = dureeConcert; } - + + public String getGenreMusical() { return genreMusical; } public void setGenreMusical(String genreMusical) { this.genreMusical = genreMusical; } - - public int getNbPlaceDispo() { - return nbPlaceDispo; + + + public int getNb_place_disponible() { + return nb_place_disponible; } - public void setNbPlaceDispo(int nbPlaceDispo) { - this.nbPlaceDispo = nbPlaceDispo; + public void setNb_place_disponible(int nb_place_disponible) { + this.nb_place_disponible = nb_place_disponible; } - - public String getDureeConcert() { - return dureeConcert; + + + public boolean isStatut_concert() { + return statut_concert; } - public void setDureeConcert(String dureeConcert) { - this.dureeConcert = dureeConcert; + public void setStatut_concert(boolean statut_concert) { + this.statut_concert = statut_concert; } - - public String getStatut() { - return statut; + + + public BigDecimal getPrix_ticket() { + return prix_ticket; } - public void setStatut(String statut) { - this.statut = statut; + public void setPrix_ticket(BigDecimal prix_ticket) { + this.prix_ticket = prix_ticket; } - - public LocalDate getDateValidation() { - return dateValidation; + + + public LocalDate getDate_concert() { + return date_concert; } - public void setDateValidation(LocalDate dateValidation) { - this.dateValidation = dateValidation; + public void setDate_concert(LocalDate date_concert) { + this.date_concert = date_concert; } - - public String getCommentairesAdmin() { - return commentairesAdmin; + + + public Manager getManager() { + return manager; + } + public void setManager(Manager manager) { + this.manager = manager; + } + + + public Admin getAdmin() { + return admin; } - public void setCommentairesAdmin(String commentairesAdmin) { - this.commentairesAdmin = commentairesAdmin; + public void setAdmin(Admin admin) { + this.admin = admin; + } + + + public List getTickets() { + return tickets; + } + public void setTickets(List tickets) { + this.tickets = tickets; } + //ToString Event @Override public String toString() { return "Event [eventId=" + eventId + ", nom=" + nom + ", description=" + description + ", artiste=" + artiste - + ", lieu=" + lieu + ", dateConcert=" + dateConcert + ", genreMusical=" + genreMusical - + ", nbPlaceDispo=" + nbPlaceDispo + ", dureeConcert=" + dureeConcert + ", statut=" + statut - + ", dateValidation=" + dateValidation + ", commentairesAdmin=" + commentairesAdmin + ", manager=" - + manager + ", admin=" + admin + ", tickets=" + tickets + "]"; + + ", lieu=" + lieu + ", dureeConcert=" + dureeConcert + ", genreMusical=" + genreMusical + + ", nb_place_disponible=" + nb_place_disponible + ", statut_concert=" + statut_concert + + ", prix_ticket=" + prix_ticket + ", date_concert=" + date_concert + ", manager=" + manager + + ", admin=" + admin + ", tickets=" + tickets + "]"; } + + + // diminuer le nombre de places disponibles + public void diminuerPlaces() { + if (this.nb_place_disponible <= 0) { + throw new IllegalArgumentException("Plus de places disponibles"); + } + this.nb_place_disponible--; + } + } \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java index 22c04715..783149d8 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Manager.java @@ -2,11 +2,9 @@ import java.io.Serializable; import java.util.List; - +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; import jakarta.persistence.NamedQuery; import jakarta.persistence.OneToMany; @@ -15,15 +13,18 @@ @NamedQuery( name = "Manager.findByEmail", query = "SELECT m FROM Manager m WHERE m.email = :emailValue" - ) +) public class Manager extends User implements Serializable { + private String manager_agence; + @OneToMany(mappedBy = "manager", cascade = CascadeType.PERSIST) + @JsonManagedReference private List events; //GETTERS - SETTERS - @OneToMany(mappedBy = "manager", cascade = CascadeType.PERSIST) + public List getEvents() { return events; } @@ -35,15 +36,14 @@ public void setEvents(List events) { @Override public String toString() { return "Manager [events=" + events + ", userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + ", email=" - + email + ", tel=" + tel + ", date_naissance=" + date_naissance + ", password=" + password + + email + ", telephone=" + telephone + ", date_naissance=" + date_naissance + ", password=" + password + ", statut_User=" + statut_user + "]"; } + public String getManager_agence() { + return manager_agence; + } + public void setManager_agence(String manager_agence) { + this.manager_agence = manager_agence; + } -// //CONSTRUCTEURS -// public Manager() { -// super(); -// } -// public Manager(String statutManager) { -// this.setStatutManager(statutManager); -// } } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Pet.java b/src/main/java/fr/istic/taa/jaxrs/domain/Pet.java deleted file mode 100644 index c8738b97..00000000 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Pet.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.istic.taa.jaxrs.domain; - -import java.util.ArrayList; -import java.util.List; - -import io.swagger.v3.oas.models.tags.Tag; -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementWrapper; -import jakarta.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "Pet") -public class Pet { - private long id; - private String name; - private List tags = new ArrayList(); - - @XmlElement(name = "id") - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - @XmlElement(name = "name") - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @XmlElementWrapper(name = "tags") - @XmlElement(name = "tag") - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } -} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java b/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java index 695ba14d..b122bcf7 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/Ticket.java @@ -4,6 +4,14 @@ import java.math.BigDecimal; import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +import fr.istic.taa.jaxrs.domain.enumeration.StatutTicket; import jakarta.persistence.*; /*import jakarta.persistence.Embeddable; import jakarta.persistence.EmbeddedId; @@ -14,38 +22,44 @@ @Entity //Requete NamedQuery @NamedQuery( - name = "Ticket.findByUserId", - query = "SELECT t FROM Ticket t WHERE t.client.userId = :user_id" + name = "Ticket.findByClientId", + query = "SELECT t FROM Ticket t WHERE t.client.userId = :client_id" ) public class Ticket implements Serializable { @EmbeddedId private TicketId id; - private int numeroPlace; - private BigDecimal prix; - private String statut; + + @Enumerated(EnumType.STRING) + private StatutTicket statut_ticket; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate dateAchat; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate dateAnnulation; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate dateRemboursement; @ManyToOne @MapsId("userId") @JoinColumn(name = "userId", nullable = false) + @JsonBackReference private Client client; @ManyToOne - @MapsId("eventId") // Map a TicketId.eventId + @MapsId("eventId") @JoinColumn(name = "eventId", nullable = false) + @JsonBackReference private Event event; - @Column(precision = 8, scale = 2) - public BigDecimal getPrix() { - return prix; - } - public void setPrix(BigDecimal prix) { - this.prix = prix; - } - // Getters et Setters public TicketId getId() { return id; } public void setId(TicketId id) { this.id = id; } @@ -56,18 +70,12 @@ public void setPrix(BigDecimal prix) { public Event getEvent() { return event; } public void setEvent(Event event) { this.event = event; } - public int getNumeroPlace() { - return numeroPlace; - } - public void setNumeroPlace(int numeroPlace) { - this.numeroPlace = numeroPlace; - } - - public String getStatut() { - return statut; + + public StatutTicket getStatut() { + return statut_ticket; } - public void setStatut(String statut) { - this.statut = statut; + public void setStatut(StatutTicket statut_ticket) { + this.statut_ticket = statut_ticket; } public LocalDate getDateAchat() { @@ -77,6 +85,7 @@ public void setDateAchat(LocalDate dateAchat) { this.dateAchat = dateAchat; } + public LocalDate getDateAnnulation() { return dateAnnulation; } @@ -84,28 +93,19 @@ public void setDateAnnulation(LocalDate dateAnnulation) { this.dateAnnulation = dateAnnulation; } + public LocalDate getDateRemboursement() { return dateRemboursement; } public void setDateRemboursement(LocalDate dateRemboursement) { this.dateRemboursement = dateRemboursement; } - - public void diminuer() { - // diminuer le nombre de places disponibles - } + @Override public String toString() { - return "Ticket [id=" + id + ", numeroPlace=" + numeroPlace + ", prix=" + prix + ", statut=" + statut + return "Ticket [id=" + id + ", numeroPlace=" + "statut_ticket= " + statut_ticket + ", dateAchat=" + dateAchat + ", dateAnnulation=" + dateAnnulation + ", dateRemboursement=" + dateRemboursement + ", client=" + client + ", event=" + event + "]"; } -} - - -////CONSTRUCTEURS -//public Ticket() {} -//public Ticket(int userId, int eventId) { -// this.id = new TicketId(userId, eventId); -//} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java b/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java index 76716b9e..9a1464f0 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/TicketId.java @@ -15,7 +15,7 @@ public class TicketId implements Serializable { public TicketId() { super(); } - public TicketId(int userId, int eventId) { + public TicketId(Long userId, Long eventId) { this.userId = userId; this.eventId = eventId; } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/User.java b/src/main/java/fr/istic/taa/jaxrs/domain/User.java index 12bf0057..32d8a79b 100644 --- a/src/main/java/fr/istic/taa/jaxrs/domain/User.java +++ b/src/main/java/fr/istic/taa/jaxrs/domain/User.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import fr.istic.taa.jaxrs.domain.enumeration.Role; @Entity @@ -19,21 +20,29 @@ ) @Inheritance(strategy = InheritanceType.JOINED) public class User implements Serializable { - + + @Id + @GeneratedValue protected long userId; + + @Enumerated(EnumType.STRING) + protected Role role; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + protected LocalDate date_naissance; + + protected boolean statut_user = true; protected String nom; protected String prenom; protected String email; - protected LocalDate date_naissance; protected String password; - protected int tel; - protected boolean statut_user; + protected String telephone; //Getters and Setters - @Id - @GeneratedValue public long getUserId() { return userId; } @@ -41,7 +50,31 @@ public void setUserId(long userId) { this.userId = userId; } - + + public Role getRole() { + return role; + } + public void setRole(Role role) { + this.role = role; + } + + + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } + + + public boolean isStatut_user() { + return statut_user; + } + public void setStatut_user(boolean statut_user) { + this.statut_user = statut_user; + } + + public String getNom() { return nom; } @@ -49,7 +82,7 @@ public void setNom(String nom) { this.nom = nom; } - + public String getPrenom() { return prenom; } @@ -65,57 +98,28 @@ public void setEmail(String email) { this.email = email; } - - public int getTel() { - return tel; - } - public void setTel(int tel) { - this.tel = tel; - } - @JsonSerialize(using = LocalDateSerializer.class) - @JsonDeserialize(using = LocalDateDeserializer.class) - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") - public LocalDate getDate_naissance() { - return date_naissance; - } - public void setDate_naissance(LocalDate date_naissance) { - this.date_naissance = date_naissance; - } - - public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } - - - public boolean isStatut_user() { - return statut_user; + + + public String getTelephone() { + return telephone; } - public void setStatut_user(boolean statut_user) { - this.statut_user = statut_user; + public void setTelephone(String telephone) { + this.telephone = telephone; } - + //ToString User @Override public String toString() { return "User [userId=" + userId + ", nom=" + nom + ", prenom=" + prenom + "]"; } - - /*public User(long userId, String nom, String prenom, String email, long tel, LocalDate dateNaiss, String mdp) { - super(); - this.userId = userId; - this.nom = nom; - this.prenom = prenom; - this.email = email; - this.tel = tel; - this.dateNaiss = dateNaiss; - this.mdp = mdp; - } - - public User() {}*/ + + } diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/NiveauAdmin.java b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/NiveauAdmin.java new file mode 100644 index 00000000..9d1d070c --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/NiveauAdmin.java @@ -0,0 +1,6 @@ +package fr.istic.taa.jaxrs.domain.enumeration; + +public enum NiveauAdmin { + + ADMIN, SUPER_ADMIN +} diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/Role.java b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/Role.java new file mode 100644 index 00000000..80c568bd --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/Role.java @@ -0,0 +1,6 @@ +package fr.istic.taa.jaxrs.domain.enumeration; + +public enum Role { + + CLIENT, MANAGER, ADMIN +} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/StatutTicket.java b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/StatutTicket.java new file mode 100644 index 00000000..196a4201 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/domain/enumeration/StatutTicket.java @@ -0,0 +1,7 @@ +package fr.istic.taa.jaxrs.domain.enumeration; + +public enum StatutTicket { + + ACHETE, ANNULE, REMBOURSE + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/AchatTicketDto.java b/src/main/java/fr/istic/taa/jaxrs/dto/AchatTicketDto.java new file mode 100644 index 00000000..ac2c80e0 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/AchatTicketDto.java @@ -0,0 +1,58 @@ +package fr.istic.taa.jaxrs.dto; + +import java.math.BigDecimal; +import java.time.LocalDate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +public class AchatTicketDto { + + private Long clientId; + private Long eventId; + private BigDecimal prix; + private String statut; + private LocalDate dateAchat; + + public Long getClientId() { + return clientId; + } + public void setClientId(Long clientId) { + this.clientId = clientId; + } + + public Long getEventId() { + return eventId; + } + public void setEventId(Long eventId) { + this.eventId = eventId; + } + + public BigDecimal getPrix() { + return prix; + } + public void setPrix(BigDecimal prix) { + this.prix = prix; + } + + public String getStatut() { + return statut; + } + public void setStatut(String statut) { + this.statut = statut; + } + + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + public LocalDate getDateAchat() { + return dateAchat; + } + public void setDateAchat(LocalDate dateAchat) { + this.dateAchat = dateAchat; + } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDto.java similarity index 92% rename from src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java rename to src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDto.java index be929111..a8be6d54 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDTO.java +++ b/src/main/java/fr/istic/taa/jaxrs/dto/ConnexionDto.java @@ -1,6 +1,6 @@ package fr.istic.taa.jaxrs.dto; -public class ConnexionDTO { +public class ConnexionDto { private String email; private String password; diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/EnregistrerManagerDto.java similarity index 76% rename from src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java rename to src/main/java/fr/istic/taa/jaxrs/dto/EnregistrerManagerDto.java index 925b2297..08db89f6 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionDTO.java +++ b/src/main/java/fr/istic/taa/jaxrs/dto/EnregistrerManagerDto.java @@ -1,64 +1,80 @@ package fr.istic.taa.jaxrs.dto; import java.time.LocalDate; - import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; -public class InscriptionDTO { +public class EnregistrerManagerDto { private String nom; private String prenom; private String email; private String password; - private int tel; + private String telephone; + private String manager_agence; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate date_naissance; - + public String getNom() { return nom; } + public void setNom(String nom) { this.nom = nom; } - + public String getPrenom() { return prenom; } + public void setPrenom(String prenom) { this.prenom = prenom; } - + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } - + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + - public int getTel() { - return tel; + public String getManager_agence() { + return manager_agence; } - public void setTel(int tel) { - this.tel = tel; + public void setManager_agence(String manager_agence) { + this.manager_agence = manager_agence; } + - @JsonSerialize(using = LocalDateSerializer.class) - @JsonDeserialize(using = LocalDateDeserializer.class) - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") public LocalDate getDate_naissance() { return date_naissance; } public void setDate_naissance(LocalDate date_naissance) { this.date_naissance = date_naissance; } + } diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/EventDto.java b/src/main/java/fr/istic/taa/jaxrs/dto/EventDto.java new file mode 100644 index 00000000..72bf4053 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/EventDto.java @@ -0,0 +1,87 @@ +package fr.istic.taa.jaxrs.dto; + +import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +public class EventDto { + private String nom; + private String description; + private String artiste; + private String lieu; + private LocalDate dateConcert; + private String genreMusical; + private int nbPlaceDispo; + private int dureeConcert; + private Long managerId; // juste l'id, pas l'objet Manager + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getArtiste() { + return artiste; + } + public void setArtiste(String artiste) { + this.artiste = artiste; + } + + public String getLieu() { + return lieu; + } + public void setLieu(String lieu) { + this.lieu = lieu; + } + + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + public LocalDate getDateConcert() { + return dateConcert; + } + public void setDateConcert(LocalDate dateConcert) { + this.dateConcert = dateConcert; + } + + public String getGenreMusical() { + return genreMusical; + } + public void setGenreMusical(String genreMusical) { + this.genreMusical = genreMusical; + } + + public int getNbPlaceDispo() { + return nbPlaceDispo; + } + public void setNbPlaceDispo(int nbPlaceDispo) { + this.nbPlaceDispo = nbPlaceDispo; + } + + public int getDureeConcert() { + return dureeConcert; + } + public void setDureeConcert(int dureeConcert) { + this.dureeConcert = dureeConcert; + } + + public Long getManagerId() { + return managerId; + } + public void setManagerId(Long managerId) { + this.managerId = managerId; + } +} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionClientDto.java similarity index 66% rename from src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java rename to src/main/java/fr/istic/taa/jaxrs/dto/InscriptionClientDto.java index 9447f226..4bf04939 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDTO.java +++ b/src/main/java/fr/istic/taa/jaxrs/dto/InscriptionClientDto.java @@ -8,74 +8,69 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; -public class UserResponseDTO { +import io.swagger.v3.oas.annotations.media.Schema; + +public class InscriptionClientDto { - private Long id; private String nom; private String prenom; private String email; - private int tel; + private String password; + private String telephone; + private boolean client_newsletter; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate date_naissance; - private String role; - protected boolean statut_user; - - public Long getId() { - return id; - } - public void setId(Long id) { - this.id = id; - } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } + public String getPrenom() { return prenom; } public void setPrenom(String prenom) { this.prenom = prenom; } + public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } - public int getTel() { - return tel; - } - public void setTel(int tel) { - this.tel = tel; - } - - - public String getRole() { - return role; + + public String getPassword() { + return password; } - public void setRole(String role) { - this.role = role; + public void setPassword(String password) { + this.password = password; } - public boolean isStatut_user() { - return statut_user; + public String getTelephone() { + return telephone; } - public void setStatut_user(boolean statut_user) { - this.statut_user = statut_user; + public void setTelephone(String telephone) { + this.telephone = telephone; } - - @JsonSerialize(using = LocalDateSerializer.class) - @JsonDeserialize(using = LocalDateDeserializer.class) - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + public LocalDate getDate_naissance() { return date_naissance; } public void setDate_naissance(LocalDate date_naissance) { this.date_naissance = date_naissance; } - + + public boolean isClient_newsletter() { + return client_newsletter; + } + public void setClient_newsletter(boolean client_newsletter) { + this.client_newsletter = client_newsletter; + } } - diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java deleted file mode 100644 index de9c4198..00000000 --- a/src/main/java/fr/istic/taa/jaxrs/dto/ModificationDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.istic.taa.jaxrs.dto; - -import java.time.LocalDate; - -public class ModificationDTO { - - private String nom; - private String prenom; - private String tel; - private LocalDate date_naissance; - - public String getNom() { - return nom; - } - public void setNom(String nom) { - this.nom = nom; - } - - public String getPrenom() { - return prenom; - } - public void setPrenom(String prenom) { - this.prenom = prenom; - } - - public String getTel() { - return tel; - } - public void setTel(String tel) { - this.tel = tel; - } - - public LocalDate getDate_naissance() { - return date_naissance; - } - public void setDate_naissance(LocalDate date_naissance) { - this.date_naissance = date_naissance; - } - -} diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java b/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDto.java similarity index 93% rename from src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java rename to src/main/java/fr/istic/taa/jaxrs/dto/PasswordDto.java index 6a1df18a..336f8e0b 100644 --- a/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDTO.java +++ b/src/main/java/fr/istic/taa/jaxrs/dto/PasswordDto.java @@ -1,6 +1,6 @@ package fr.istic.taa.jaxrs.dto; -public class PasswordDTO { +public class PasswordDto { private String oldPassword; private String newPassword; diff --git a/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDto.java b/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDto.java new file mode 100644 index 00000000..d165dce8 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/dto/UserResponseDto.java @@ -0,0 +1,126 @@ +package fr.istic.taa.jaxrs.dto; + +import java.time.LocalDate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; + +import fr.istic.taa.jaxrs.domain.enumeration.NiveauAdmin; +import fr.istic.taa.jaxrs.domain.enumeration.Role; +import io.swagger.v3.oas.annotations.media.Schema; + +public class UserResponseDto { + + private Long id; + private String nom; + private String prenom; + private String email; + private String telephone; + private Role role; + private boolean statut_user; + + // attributs spécifique pour Manager + @Schema(description = "Concerne seuleument CLIENT", nullable = true) + private boolean client_newsletter; + + @Schema(description = "Concerne seuleument MANAGER", nullable = true) + private String manager_agence; + + @Schema(description = "Niveau de l'admin (uniquement si rôle ADMIN)", example = "ADMIN", nullable = true) + private NiveauAdmin admin_niveau; + + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate date_naissance; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + public String getNom() { + return nom; + } + public void setNom(String nom) { + this.nom = nom; + } + + + public String getPrenom() { + return prenom; + } + public void setPrenom(String prenom) { + this.prenom = prenom; + } + + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + + public String getTelephone() { + return telephone; + } + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + + public Role getRole() { + return role; + } + public void setRole(Role role) { + this.role = role; + } + + + public boolean isStatut_user() { + return statut_user; + } + public void setStatut_user(boolean statut_user) { + this.statut_user = statut_user; + } + + + public LocalDate getDate_naissance() { + return date_naissance; + } + public void setDate_naissance(LocalDate date_naissance) { + this.date_naissance = date_naissance; + } + + public boolean isClient_newsletter() { + return client_newsletter; + } + public void setClient_newsletter(boolean client_newsletter) { + this.client_newsletter = client_newsletter; + } + public String getManager_agence() { + return manager_agence; + } + public void setManager_agence(String manager_agence) { + this.manager_agence = manager_agence; + } + public NiveauAdmin getAdmin_niveau() { + return admin_niveau; + } + public void setAdmin_niveau(NiveauAdmin admin_niveau) { + this.admin_niveau = admin_niveau; + } + + + +} + diff --git a/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java b/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java index ab1055fc..d27d8da9 100644 --- a/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java +++ b/src/main/java/fr/istic/taa/jaxrs/jpa/JpaTest.java @@ -1,67 +1,11 @@ -package fr.istic.taa.jaxrs.jpa; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityTransaction; -import fr.istic.taa.jaxrs.dao.ManagerDao; -import fr.istic.taa.jaxrs.dao.UserDao; -import fr.istic.taa.jaxrs.domain.Manager; -import fr.istic.taa.jaxrs.domain.User; - -public class JpaTest { - - - private EntityManager manager; - - public JpaTest(EntityManager manager) { - this.manager = manager; - } - /** - * @param args - */ - public static void main(String[] args) { - /*EntityManager manager = EntityManagerHelper.getEntityManager(); - - JpaTest test = new JpaTest(manager); - - EntityTransaction tx = manager.getTransaction(); - tx.begin();*/ - - //cree directement l'utilisateur lié - - ManagerDao managerDao = new ManagerDao(); - Manager m = new Manager(); - m.setNom("Dupont"); - m.setPrenom("Jean"); - m.setStatut_user(true); - managerDao.save(m); - System.out.println(managerDao.findAll()); - -// ManagerDao managerDao = new ManagerDao(); -// System.out.println(managerDao.findMangersActifs()); - -// UserDao userDao = new UserDao(); -// System.out.println(userDao.findUsersByNom("Aryath")); - - try { - - // TODO create and persist entity - } catch (Exception e) { - e.printStackTrace(); - } - /*tx.commit(); - - - manager.close(); - EntityManagerHelper.closeEntityManagerFactory();*/ - System.out.println(".. done"); - } - -} - //package fr.istic.taa.jaxrs.jpa; // //import jakarta.persistence.EntityManager; //import jakarta.persistence.EntityTransaction; +//import fr.istic.taa.jaxrs.dao.ManagerDao; +//import fr.istic.taa.jaxrs.dao.UserDao; +//import fr.istic.taa.jaxrs.domain.Manager; +//import fr.istic.taa.jaxrs.domain.User; // //public class JpaTest { // @@ -82,18 +26,74 @@ public static void main(String[] args) { // EntityTransaction tx = manager.getTransaction(); // tx.begin(); // +// //cree directement l'utilisateur lié +// +//// ManagerDao managerDao = new ManagerDao(); +//// Manager m = new Manager(); +//// m.setNom("Dupont"); +//// m.setPrenom("Jean"); +//// m.setStatut_user(true); +//// managerDao.save(m); +//// System.out.println(managerDao.findAll()); +//// +//// ManagerDao managerDao = new ManagerDao(); +//// System.out.println(managerDao.findMangersActifs()); +//// +//// UserDao userDao = new UserDao(); +//// System.out.println(userDao.findUsersByNom("Aryath")); +// // try { // // // TODO create and persist entity // } catch (Exception e) { // e.printStackTrace(); // } -// tx.commit(); +// /*tx.commit(); // // // manager.close(); -// EntityManagerHelper.closeEntityManagerFactory(); +// EntityManagerHelper.closeEntityManagerFactory();*/ // System.out.println(".. done"); // } // //} + +package fr.istic.taa.jaxrs.jpa; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityTransaction; + +public class JpaTest { + + + private EntityManager manager; + + public JpaTest(EntityManager manager) { + this.manager = manager; + } + /** + * @param args + */ + public static void main(String[] args) { + EntityManager manager = EntityManagerHelper.getEntityManager(); + + JpaTest test = new JpaTest(manager); + + EntityTransaction tx = manager.getTransaction(); + tx.begin(); + + try { + + // TODO create and persist entity + } catch (Exception e) { + e.printStackTrace(); + } + tx.commit(); + + + manager.close(); + EntityManagerHelper.closeEntityManagerFactory(); + System.out.println(".. done"); + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/AdminResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/AdminResource.java new file mode 100644 index 00000000..cbc77c93 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/AdminResource.java @@ -0,0 +1,50 @@ +package fr.istic.taa.jaxrs.rest; + +import fr.istic.taa.jaxrs.dao.AdminDao; +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.dto.InscriptionClientDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; +import fr.istic.taa.jaxrs.service.AdminService; +import fr.istic.taa.jaxrs.service.ClientService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.Response; + + +@Path("admin") +@Produces({"application/json", "application/xml"}) +@Tag(name = "Admin", description = "Gestion des Admin") +public class AdminResource { + + private AdminService adminService; + + public AdminResource() { + AdminDao adminDao = new AdminDao(); + this.adminService = new AdminService(adminDao); + } + + + //liste des utilisateurs + @GET + @Path("/all") + @Operation(summary = "Lister tous les Admins", description = "Retourne la liste de tous les Admins") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Admins trouvés avec succes", + content = @Content(schema = @Schema(implementation = UserResponseDto.class))) + }) + public Response listeUtilisateurs() { + return Response.ok(adminService.listeAdmins()).build(); + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/ClientResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/ClientResource.java new file mode 100644 index 00000000..ebd20463 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/ClientResource.java @@ -0,0 +1,68 @@ +package fr.istic.taa.jaxrs.rest; + +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.domain.Client; +import fr.istic.taa.jaxrs.dto.ConnexionDto; +import fr.istic.taa.jaxrs.dto.InscriptionClientDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; +import fr.istic.taa.jaxrs.service.ClientService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.Response; + +@Path("client") +@Produces({"application/json", "application/xml"}) +@Tag(name = "Client", description = "Gestion des Clients") +public class ClientResource { + + private ClientService clientService; + + public ClientResource() { + ClientDao clientDao = new ClientDao(); + UserDao userDao = new UserDao(); + this.clientService = new ClientService(clientDao, userDao); + } + + + + @POST + @Path("/inscription") + @Consumes("application/json") + @Operation(summary = "S'inscrire", description = "Permet à un utilisateur de S'inscrire") + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "Inscrition réussie", + content = @Content(schema = @Schema(implementation = UserResponseDto.class))), + @ApiResponse(responseCode = "400", description = "Email déjà utilisé") + }) + public Response inscription( + @RequestBody( + description = "body de l'api", + required = true, + content = @Content(schema = @Schema(implementation = InscriptionClientDto.class)) + ) + InscriptionClientDto dto) { + try { + UserResponseDto response = clientService.inscription(dto); + return Response.status(Response.Status.CREATED).entity(response).build(); + } catch (Exception e) { + // TODO: handle exception + System.out.println(e.getMessage()); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + +} + + + + diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java b/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java deleted file mode 100644 index b5d51942..00000000 --- a/src/main/java/fr/istic/taa/jaxrs/rest/ClientRessource.java +++ /dev/null @@ -1,49 +0,0 @@ -package fr.istic.taa.jaxrs.rest; - -import fr.istic.taa.jaxrs.dao.ClientDao; -import fr.istic.taa.jaxrs.dao.UserDao; -import fr.istic.taa.jaxrs.domain.Client; -import fr.istic.taa.jaxrs.dto.ClientResponseDTO; -import fr.istic.taa.jaxrs.dto.InscriptionDTO; -import fr.istic.taa.jaxrs.dto.UserResponseDTO; -import fr.istic.taa.jaxrs.service.ClientService; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Response; - -@Path("client") -@Produces({"application/json", "application/xml"}) -public class ClientRessource { - - private ClientService clientService; - - public ClientRessource() { - ClientDao clientDao = new ClientDao(); - UserDao UserDao = new UserDao(); - this.clientService = new ClientService(clientDao, UserDao); - } - - - - @POST - @Path("/inscrire") - @Consumes("application/json") - //@Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) - public Response inscription(InscriptionDTO dto) { - try { - UserResponseDTO response = clientService.inscription(dto); - return Response.status(Response.Status.CREATED).entity(response).build(); - } catch (Exception e) { - // TODO: handle exception - System.out.println(e.getMessage()); - return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); - } - } - -} - - - - diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/EventResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/EventResource.java new file mode 100644 index 00000000..e0af69ba --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/EventResource.java @@ -0,0 +1,74 @@ +package fr.istic.taa.jaxrs.rest; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import fr.istic.taa.jaxrs.dao.EventDao; +import fr.istic.taa.jaxrs.dao.ManagerDao; +import fr.istic.taa.jaxrs.domain.Event; +import fr.istic.taa.jaxrs.dto.EventDto; +import fr.istic.taa.jaxrs.service.EventService; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; + + +@Path("event") +@Produces({"application/json", "application/xml"}) +public class EventResource { + + private EventService eventService; + + public EventResource() { + EventDao eventDao = new EventDao(); + ManagerDao managerDao = new ManagerDao(); + this.eventService = new EventService(managerDao, eventDao); + } + + @POST + @Path("/create") + @Consumes("application/json") + public Response creerEvent(EventDto dto) { + try { + Event newEvent = eventService.creerEvent(dto); + return Response.status(Response.Status.CREATED) + .entity(newEvent) + .build(); + } catch (IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .build(); + } + } + + @GET + @Path("/all/{managerId}") + public Response findEventsByManagerId(@PathParam("managerId") Long manager_Id) { + return Response.ok(eventService.findEventsByManagerId(manager_Id)).build(); + } + + + @GET + @Path("all/date") + public Response findEventsByDate(@QueryParam("date") String dateStr) { + if (dateStr == null) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("La date est obligatoire") + .build(); + } + try { + LocalDate date = LocalDate.parse(dateStr); + return Response.ok(eventService.findEventsByDate(date)).build(); + } catch (DateTimeParseException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("Format de date invalide, utilisez YYYY-MM-DD") + .build(); + } + } + +// @GET +// @Path("all/date") +// public Response findEventsByDate(@QueryParam("date") String dateStr) { +// LocalDate date = LocalDate.parse(dateStr); +// return Response.ok(eventService.findEventsByDate(date)).build(); +// } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/ManagerResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/ManagerResource.java new file mode 100644 index 00000000..6abc6bc1 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/ManagerResource.java @@ -0,0 +1,60 @@ +package fr.istic.taa.jaxrs.rest; + +import fr.istic.taa.jaxrs.dao.ManagerDao; +import fr.istic.taa.jaxrs.dao.UserDao; +import fr.istic.taa.jaxrs.dto.EnregistrerManagerDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; +import fr.istic.taa.jaxrs.service.ManagerService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; + + +@Path("manager") +@Produces({"application/json", "application/xml"}) +@Tag(name = "Manager", description = "Gestion des Manager") +public class ManagerResource { + + private ManagerService managerService; + + public ManagerResource() { + ManagerDao managerDao = new ManagerDao(); + UserDao userDao = new UserDao(); + this.managerService = new ManagerService(managerDao, userDao); + } + + + + @POST + @Path("/ajouter") + @Consumes("application/json") + @Operation(summary = "Ajouter Manager", description = "Enregistrer un Manager") + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "Ajout réussie", + content = @Content(schema = @Schema(implementation = UserResponseDto.class))), + @ApiResponse(responseCode = "400", description = "Email déjà utilisé") + }) + public Response ajouterManager( +// @RequestBody( +// description = "body de l'api", +// required = true, +// content = @Content(schema = @Schema(implementation = InscriptionDto.class)) +// ) + EnregistrerManagerDto dto) { + try { + UserResponseDto response = managerService.ajouterManager(dto); + return Response.status(Response.Status.CREATED).entity(response).build(); + } catch (Exception e) { + // TODO: handle exception + System.out.println(e.getMessage()); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/PetResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/PetResource.java deleted file mode 100644 index 30873955..00000000 --- a/src/main/java/fr/istic/taa/jaxrs/rest/PetResource.java +++ /dev/null @@ -1,38 +0,0 @@ -package fr.istic.taa.jaxrs.rest; - -import fr.istic.taa.jaxrs.domain.Pet; -import io.swagger.v3.oas.annotations.Parameter; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Response; - -@Path("pet") -@Produces({"application/json", "application/xml"}) -public class PetResource { - - @GET - @Path("/{petId}") - public Pet getPetById(@PathParam("petId") Long petId) { - // return pet - return new Pet(); - } - - @GET - @Path("/") - public Pet getPet(Long petId) { - return new Pet(); - } - - - @POST - @Consumes("application/json") - public Response addPet( - @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { - // add pet - return Response.ok().entity("SUCCESS").build(); - } -} \ No newline at end of file diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/SwaggerResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/SwaggerResource.java new file mode 100644 index 00000000..eff662b7 --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/SwaggerResource.java @@ -0,0 +1,34 @@ +package fr.istic.taa.jaxrs.rest; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.logging.Logger; +import jakarta.ws.rs.*; +import jakarta.ws.rs.Path; + +@Path("/api") +public class SwaggerResource { + + private static final Logger logger = Logger.getLogger(SwaggerResource.class.getName()); + + @GET + public byte[] Get1() { + try { + return Files.readAllBytes(FileSystems.getDefault().getPath("src/main/webapp/swagger/dist/index.html")); + } catch (IOException e) { + return null; + } + } + + @GET + @Path("{path:.*}") + public byte[] Get(@PathParam("path") String path) { + try { + return Files.readAllBytes(FileSystems.getDefault().getPath("src/main/webapp/swagger/dist/"+path)); + } catch (IOException e) { + return null; + } + } + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/TicketResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/TicketResource.java new file mode 100644 index 00000000..4c16148d --- /dev/null +++ b/src/main/java/fr/istic/taa/jaxrs/rest/TicketResource.java @@ -0,0 +1,87 @@ +package fr.istic.taa.jaxrs.rest; + + +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.EventDao; +import fr.istic.taa.jaxrs.dao.TicketDao; +import fr.istic.taa.jaxrs.domain.Ticket; +import fr.istic.taa.jaxrs.dto.AchatTicketDto; +import fr.istic.taa.jaxrs.service.TicketService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; + +@Path("ticket") +@Produces({"application/json", "application/xml"}) +@Tag(name = "Ticket", description = "Gestion des tickets") +public class TicketResource { + + private TicketService ticketService; + + public TicketResource() { + ClientDao clientDao = new ClientDao(); + EventDao eventDao = new EventDao(); + TicketDao ticketDao = new TicketDao(); + this.ticketService = new TicketService(clientDao, eventDao, ticketDao); + } + + + @POST + @Path("/acheter") + @Consumes("application/json") + @Operation( + summary = "Acheter un ticket", + description = "Permet à un client d'acheter un ticket pour un événement" + ) + @ApiResponses({ + @ApiResponse( + responseCode = "201", + description = "Ticket acheté avec succès", + content = @Content(schema = @Schema(implementation = Ticket.class)) + ), + @ApiResponse( + responseCode = "400", + description = "Erreur lors de l'achat (plus de places, client introuvable...)", + content = @Content(schema = @Schema(implementation = String.class)) + ) + }) + public Response acheterTicket(AchatTicketDto dto) { + try { + Ticket ticket = ticketService.acheterTicket(dto); + return Response.status(Response.Status.CREATED).entity(ticket).build(); + } catch (Exception e) { + // TODO: handle exception + System.out.println(e.getMessage()); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + + @GET + @Path("/all/{clientId}") + @Operation( + summary = "Récupérer les tickets d'un client", + description = "Retourne la liste de tous les tickets achetés par un client" + ) + @ApiResponses({ + @ApiResponse( + responseCode = "200", + description = "Liste des tickets du client", + content = @Content(schema = @Schema(implementation = Ticket.class)) + ), + @ApiResponse( + responseCode = "404", + description = "Client introuvable" + ) + }) + public Response findEventsByManagerId(@PathParam("clientId") Long clientId) { + return Response.ok(ticketService.findTicketsByClientId(clientId)).build(); + } + + +} diff --git a/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java index 4154c0aa..f46ebc21 100644 --- a/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java +++ b/src/main/java/fr/istic/taa/jaxrs/rest/UserResource.java @@ -1,20 +1,24 @@ package fr.istic.taa.jaxrs.rest; -import org.hibernate.service.spi.InjectService; - -import fr.istic.taa.jaxrs.dao.ManagerDao; import fr.istic.taa.jaxrs.dao.UserDao; -import fr.istic.taa.jaxrs.domain.Manager; -import fr.istic.taa.jaxrs.domain.User; -import fr.istic.taa.jaxrs.dto.ConnexionDTO; -import fr.istic.taa.jaxrs.dto.PasswordDTO; -import fr.istic.taa.jaxrs.dto.UserResponseDTO; +import fr.istic.taa.jaxrs.dto.ConnexionDto; +import fr.istic.taa.jaxrs.dto.PasswordDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; import fr.istic.taa.jaxrs.service.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; @Path("user") @Produces({"application/json", "application/xml"}) +@Tag(name = "User", description = "Gestion des Utilisateurs") public class UserResource { private UserService userService; @@ -23,25 +27,56 @@ public UserResource() { UserDao userDao = new UserDao(); this.userService = new UserService(userDao); } - -// @GET -// @Path("/{user_id}") -// public Response getUserById(@PathParam("user_id") Long user_id) { -// // appel DAO -// User user = userDao.findOne(user_id); -// -// if(user != null){ -// return Response.ok(user).build(); -// } -// return Response.status(Response.Status.NOT_FOUND).build(); -// } + // Connexion + @POST + @Path("/connexion") + @Consumes("application/json") + @Operation(summary = "Se connecter", description = "Permet à un utilisateur de se connecter") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Connexion réussie", + content = @Content(schema = @Schema(implementation = UserResponseDto.class))), + @ApiResponse(responseCode = "401", description = "Email ou mot de passe incorrect") + }) + public Response connexion( + @RequestBody( + description = "Email et mot de passe de l'utilisateur", + required = true, + content = @Content(schema = @Schema(implementation = ConnexionDto.class)) + ) + ConnexionDto dto) { + + // user contient juste email + password + try { + UserResponseDto response = userService.seConnecter(dto); + return Response.ok(response).build(); + } catch (Exception e) { + return Response.status(401).entity("Email ou mot de passe incorrect").build(); + } + + } + // Modification mot de passe @PUT - @Path("/updatePassword/{user_id}") - public Response modifierPassword(@PathParam("user_id") Long user_id, PasswordDTO dto) { - // user contient juste l'ancien et le nouveau password + @Path("/updatePassword/user_id/{user_id}") + @Consumes("application/json") + @Operation(summary = "Modifier le mot de passe", description = "Permet de changer le mot de passe d'un utilisateur") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Mot de passe modifié avec succès"), + @ApiResponse(responseCode = "400", description = "Ancien mot de passe incorrect ou données invalides"), + @ApiResponse(responseCode = "404", description = "Utilisateur non trouvé") + }) + public Response modifierPassword( + @Parameter(description = "ID de l'utilisateur", required = true, example = "1") + @PathParam("user_id") Long user_id, + + @RequestBody( + description = "Ancien et nouveau mot de passe", + required = true, + content = @Content(schema = @Schema(implementation = PasswordDto.class)) + )PasswordDto dto) { + try { userService.changerMdp(user_id, dto); return Response.ok("Mot de passe modifié").build(); @@ -51,19 +86,15 @@ public Response modifierPassword(@PathParam("user_id") Long user_id, PasswordDTO } - @POST - @Path("/connexion") - @Consumes("application/json") - public Response connection(ConnexionDTO dto) { - - // user contient juste email + password - try { - UserResponseDTO response = userService.seConnecter(dto); - return Response.ok(response).build(); - } catch (Exception e) { - return Response.status(401).entity("Email ou mot de passe incorrect").build(); + //liste des utilisateurs + @GET + @Path("/all") + @Operation(summary = "Lister tous les utilisateurs", description = "Retourne la liste de tous les utilisateurs") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Utilisateurs trouvés avec succes", + content = @Content(schema = @Schema(implementation = UserResponseDto.class))) + }) + public Response listeUtilisateurs() { + return Response.ok(userService.listeUtilisateurs()).build(); } - - } - } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java b/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java index 92f5b4d5..35834eef 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/AdminService.java @@ -1,12 +1,39 @@ package fr.istic.taa.jaxrs.service; +import java.util.ArrayList; +import java.util.List; + +import fr.istic.taa.jaxrs.dao.AdminDao; +import fr.istic.taa.jaxrs.domain.Admin; +import fr.istic.taa.jaxrs.dto.UserResponseDto; + public class AdminService { - -// AdminService -// Regroupe les actions de modération. -// -// validerEvenement(Long concertId) : Appelle ConcertDao pour passer le statut à "Validé". Peut envoyer un mail de notification à l'organisateur. -// -// gererAccesUtilisateur(Long userId, boolean suspendre) : Appelle UserDao pour modifier le statut du compte. + + private AdminDao adminDao; + // Injection par constructeur + public AdminService(AdminDao adminDao) { + this.adminDao = adminDao; + } + + // Liste des Admins + public List listeAdmins() { + List admins = adminDao.findAll(); + List dtos = new ArrayList<>(); + + for (Admin a : admins) { + UserResponseDto dto = new UserResponseDto(); + dto.setId(a.getUserId()); + dto.setNom(a.getNom()); + dto.setPrenom(a.getPrenom()); + dto.setEmail(a.getEmail()); + dto.setTelephone(a.getTelephone()); + dto.setRole(a.getRole()); + dto.setStatut_user(a.isStatut_user()); + dto.setAdmin_niveau(a.getAdmin_niveau()); + dtos.add(dto); + } + return dtos; + } + } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java index 86e9d12f..7ea06388 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/ClientService.java @@ -5,6 +5,7 @@ import fr.istic.taa.jaxrs.dao.ClientDao; import fr.istic.taa.jaxrs.dao.UserDao; import fr.istic.taa.jaxrs.domain.Client; +import fr.istic.taa.jaxrs.domain.enumeration.Role; import fr.istic.taa.jaxrs.dto.*; public class ClientService { @@ -19,8 +20,8 @@ public ClientService(ClientDao clientDao, UserDao userDao) { } - //1-Methode metier S'inscrire - public UserResponseDTO inscription(InscriptionDTO dto) throws Exception { + //Methode metier S'inscrire + public UserResponseDto inscription(InscriptionClientDto dto) throws Exception { if (this.userDao.findByEmailNamedQuery(dto.getEmail()) != null) { throw new Exception("Email déjà utilisé"); @@ -31,9 +32,10 @@ public UserResponseDTO inscription(InscriptionDTO dto) throws Exception { client.setNom(dto.getNom()); client.setPrenom(dto.getPrenom()); client.setEmail(dto.getEmail()); - client.setTel(dto.getTel()); + client.setTelephone(dto.getTelephone()); client.setDate_naissance(dto.getDate_naissance()); - client.setStatut_user(true); + client.setClient_newsletter(dto.isClient_newsletter()); + client.setRole(Role.CLIENT); String hashed = BCrypt.hashpw(dto.getPassword(), BCrypt.gensalt()); client.setPassword(hashed); @@ -41,20 +43,19 @@ public UserResponseDTO inscription(InscriptionDTO dto) throws Exception { this.clientDao.save(client); // Appel simple au DAO // Mapper vers DTO de réponse - UserResponseDTO response = new UserResponseDTO(); + UserResponseDto response = new UserResponseDto(); response.setId(client.getUserId()); response.setNom(client.getNom()); response.setPrenom(client.getPrenom()); response.setEmail(client.getEmail()); - response.setTel(client.getTel()); + response.setTelephone(client.getTelephone()); response.setStatut_user(client.isStatut_user()); response.setDate_naissance(client.getDate_naissance()); - - response.setRole("CLIENT"); //### A revoir + response.setRole(client.getRole()); + response.setClient_newsletter(client.isClient_newsletter()); return response; } - //2-Methode metier Se Connecter (voir User) } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/EventService.java b/src/main/java/fr/istic/taa/jaxrs/service/EventService.java index 07c00852..2955ac56 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/EventService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/EventService.java @@ -1,9 +1,64 @@ package fr.istic.taa.jaxrs.service; +import java.time.LocalDate; +import java.util.List; + +import fr.istic.taa.jaxrs.dao.EventDao; +import fr.istic.taa.jaxrs.dao.ManagerDao; +import fr.istic.taa.jaxrs.domain.Event; +import fr.istic.taa.jaxrs.domain.Manager; +import fr.istic.taa.jaxrs.dto.EventDto; + public class EventService { + + private EventDao eventDao; + private ManagerDao managerDao; + + // Injection par constructeur + public EventService(ManagerDao managerDao, EventDao eventDao) { + this.managerDao = managerDao; + this.eventDao = eventDao; + } + + + public Event creerEvent(EventDto dto) { + Manager manager = managerDao.findOne(dto.getManagerId()); + if (manager == null) { + throw new IllegalArgumentException("Manager introuvable"); + } + + Event event = new Event(); + event.setNom(dto.getNom()); + event.setDescription(dto.getDescription()); + event.setArtiste(dto.getArtiste()); + event.setLieu(dto.getLieu()); + event.setDate_concert(dto.getDateConcert()); + event.setGenreMusical(dto.getGenreMusical()); + event.setNb_place_disponible(dto.getNbPlaceDispo()); + event.setDureeConcert(dto.getDureeConcert()); + event.setManager(manager); + + eventDao.save(event); + + return event; + } + + + public List findEventsByDate(LocalDate date) { + + if (date == null) { + throw new IllegalArgumentException("La date ne peut pas être nulle"); + } + return eventDao.findByDateEventNamedQuery(date); + } -// ConcertService -// rechercherConcerts(String query) : Filtre les concerts disponibles (et validés par l'admin !) via le ConcertDao. + public List findEventsByManagerId(Long managerId) { + + if (this.managerDao.findOne(managerId) == null) { + throw new IllegalArgumentException("Manager Introuvable"); + } + return eventDao.findByManagerId(managerId); + } } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java b/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java index 052c867c..eb519156 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/ManagerService.java @@ -1,9 +1,11 @@ package fr.istic.taa.jaxrs.service; import org.mindrot.jbcrypt.BCrypt; - import fr.istic.taa.jaxrs.dao.*; import fr.istic.taa.jaxrs.domain.*; +import fr.istic.taa.jaxrs.domain.enumeration.Role; +import fr.istic.taa.jaxrs.dto.EnregistrerManagerDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; public class ManagerService { @@ -15,15 +17,43 @@ public ManagerService(ManagerDao managerDao, UserDao userDao) { this.userDao = userDao; } - //1-Methode metier inscrire Manager - public void inscriptionManager(Manager manager) throws Exception { + //1-Methode metier ajouter Manager + public UserResponseDto ajouterManager(EnregistrerManagerDto dto) throws Exception { - if (this.userDao.findByEmailNamedQuery(manager.getEmail()) != null) { + if (this.userDao.findByEmailNamedQuery(dto.getEmail()) != null) { throw new Exception("Email déjà utilisé"); } + + Manager manager = new Manager(); + + manager.setNom(dto.getNom()); + manager.setPrenom(dto.getPrenom()); + manager.setEmail(dto.getEmail()); + manager.setTelephone(dto.getTelephone()); + manager.setDate_naissance(dto.getDate_naissance()); + manager.setRole(Role.MANAGER); + manager.setManager_agence(dto.getManager_agence()); + String tempPassword = manager.getNom()+("123"); // ex: "Kouassi123" manager.setPassword(BCrypt.hashpw(tempPassword, BCrypt.gensalt())); - this.managerDao.save(manager); // Appel simple au DAO + + this.managerDao.save(manager); + + + + // Mapper vers DTO de réponse + UserResponseDto response = new UserResponseDto(); + response.setId(manager.getUserId()); + response.setNom(manager.getNom()); + response.setPrenom(manager.getPrenom()); + response.setEmail(manager.getEmail()); + response.setTelephone(manager.getTelephone()); + response.setStatut_user(manager.isStatut_user()); + response.setDate_naissance(manager.getDate_naissance()); + response.setRole(manager.getRole()); + response.setManager_agence(manager.getManager_agence()); + + return response; } diff --git a/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java b/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java index d3395345..37902754 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/TicketService.java @@ -1,6 +1,72 @@ package fr.istic.taa.jaxrs.service; +import java.util.List; + +import fr.istic.taa.jaxrs.dao.ClientDao; +import fr.istic.taa.jaxrs.dao.EventDao; +import fr.istic.taa.jaxrs.dao.TicketDao; +import fr.istic.taa.jaxrs.domain.*; +import fr.istic.taa.jaxrs.domain.enumeration.StatutTicket; +import fr.istic.taa.jaxrs.dto.AchatTicketDto; +import jakarta.transaction.Transactional; + public class TicketService { + + + private ClientDao clientDao; + private EventDao eventDao; + private TicketDao ticketDao; + + // Injection par constructeur + public TicketService(ClientDao clientDao, EventDao eventDao, TicketDao ticketDao) { + this.clientDao = clientDao; + this.eventDao = eventDao; + this.ticketDao = ticketDao; + } + + + // Acheter Ticket + @Transactional + public Ticket acheterTicket(AchatTicketDto dto) { + + Client client = clientDao.findOne(dto.getClientId()); + Event event = eventDao.findOne(dto.getEventId()); + if (event.getNb_place_disponible() <= 0) { + throw new RuntimeException("Plus de places disponibles"); + } + + + // Construire la clé composite + TicketId ticket_id = new TicketId(dto.getClientId(), dto.getEventId()); + // Vérifier que ce client n'a pas déjà un ticket pour cet event + if (ticketDao.findOne(ticket_id) != null) { + throw new RuntimeException("Vous avez déjà un ticket pour cet event"); + } + + + Ticket ticket = new Ticket(); + ticket.setId(ticket_id); + ticket.setStatut(StatutTicket.ACHETE); + ticket.setDateAchat(dto.getDateAchat()); + ticket.setEvent(event); + ticket.setClient(client); + ticketDao.save(ticket); + + event.diminuerPlaces(); + eventDao.save(event); + + return ticket; + } + + + public List findTicketsByClientId(Long clientId) { + + if (this.clientDao.findOne(clientId) == null) { + throw new IllegalArgumentException("Client Introuvable"); + } + return ticketDao.findByClientIdNamedQuery(clientId); + } + // TicketService // diff --git a/src/main/java/fr/istic/taa/jaxrs/service/UserService.java b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java index 1393ac7a..0ae7cf90 100644 --- a/src/main/java/fr/istic/taa/jaxrs/service/UserService.java +++ b/src/main/java/fr/istic/taa/jaxrs/service/UserService.java @@ -1,12 +1,15 @@ package fr.istic.taa.jaxrs.service; +import java.util.ArrayList; +import java.util.List; + import org.mindrot.jbcrypt.BCrypt; import fr.istic.taa.jaxrs.dao.UserDao; import fr.istic.taa.jaxrs.domain.*; import fr.istic.taa.jaxrs.domain.User; -import fr.istic.taa.jaxrs.dto.ConnexionDTO; -import fr.istic.taa.jaxrs.dto.PasswordDTO; -import fr.istic.taa.jaxrs.dto.UserResponseDTO; +import fr.istic.taa.jaxrs.dto.ConnexionDto; +import fr.istic.taa.jaxrs.dto.PasswordDto; +import fr.istic.taa.jaxrs.dto.UserResponseDto; public class UserService { @@ -19,7 +22,7 @@ public UserService(UserDao userDao) { //1-Methode seConnecter - public UserResponseDTO seConnecter(ConnexionDTO dto) { + public UserResponseDto seConnecter(ConnexionDto dto) { // 1. On demande au DAO de nous donner l'utilisateur par son email User user = userDao.findByEmailNamedQuery(dto.getEmail()); @@ -27,46 +30,31 @@ public UserResponseDTO seConnecter(ConnexionDTO dto) { throw new RuntimeException("Utilisateur non trouvé"); } - // 2. C'est ICI qu'on utilise la fonction de comparaison - // On ne fait JAMAIS "if (motDePasseSaisi == user.getPassword())" + // 2. on va utiliser la fonction de comparaison boolean match = BCrypt.checkpw(dto.getPassword(), user.getPassword()); if (!match) { throw new RuntimeException("Mot de passe incorrect"); } - - - String role = null; - if (user instanceof Client) { - role = "CLIENT"; - } else if (user instanceof Manager) { - role = "MANAGER"; - } else if (user instanceof Admin) { - role = "ADMIN"; - } - // Mapper vers DTO de réponse - UserResponseDTO response = new UserResponseDTO(); + // 3. Mapper vers UserResponseDTO + UserResponseDto response = new UserResponseDto(); response.setId(user.getUserId()); response.setNom(user.getNom()); response.setPrenom(user.getPrenom()); response.setEmail(user.getEmail()); - response.setTel(user.getTel()); + response.setTelephone(user.getTelephone()); response.setStatut_user(user.isStatut_user()); response.setDate_naissance(user.getDate_naissance()); - - response.setRole(role); //### A revoir + response.setRole(user.getRole()); return response; // Connexion réussie } - - //Déconnexion Invalide la session en cours ou supprime le token (pas besoin du DAO ici en général). - //2- Modifier MDP - public void changerMdp(Long user_id, PasswordDTO dto) throws Exception { + public void changerMdp(Long user_id, PasswordDto dto) throws Exception { User user = userDao.findOne(user_id); @@ -77,7 +65,7 @@ public void changerMdp(Long user_id, PasswordDTO dto) throws Exception { boolean match = BCrypt.checkpw(dto.getOldPassword(), user.getPassword()); if (!match) { - throw new RuntimeException("Ancien mot de passe incorrect"); + throw new RuntimeException("Ancien mot de passe incorrect ou données invalides"); } String hashed = BCrypt.hashpw(dto.getNewPassword(), BCrypt.gensalt()); @@ -86,4 +74,24 @@ public void changerMdp(Long user_id, PasswordDTO dto) throws Exception { this.userDao.update(user); } + + + //3- Liste des utilisateurs + public List listeUtilisateurs() { + List users = userDao.findAllUser(); + List dtos = new ArrayList<>(); + + for (User u : users) { + UserResponseDto dto = new UserResponseDto(); + dto.setId(u.getUserId()); + dto.setNom(u.getNom()); + dto.setPrenom(u.getPrenom()); + dto.setEmail(u.getEmail()); + dto.setTelephone(u.getTelephone()); + dto.setRole(u.getRole()); + dto.setStatut_user(u.isStatut_user()); + dtos.add(dto); + } + return dtos; + } } diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 5997d427..b07408c7 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -16,7 +16,7 @@ - + diff --git a/src/main/webapp/.DS_Store b/src/main/webapp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5b3ba5f8b27f9c70c3529094ffe03067a57f757f GIT binary patch literal 6148 zcmeHK%}T>S5T0$TO({YT3LY1{7Ht$O;w4r+cr~I2m73U6gE1>jYYwH5v%Zi|;_K+l z?zW)Sn~0T}F#ApBC&_*ZyBPowtzpLnr~!b3N?54i@P$yEbVdr+Q$!T{8a?Pj|2S4R zVLX$~j=#tNy}L4`kU;=FJf`nYg&3jFVjp$=O$%Bx*vFW~x^>xfcgEw2v$D3achbI#?-TW;pBn^z zqgs|MPT(1hPaHh@{UlaN4bkf2M)RgKrEqK3)=M4NHx-;XE8U35fouc5lyMEEru}V=$AInvzQw+PvbP%3F9+?4V;3EUn`=Qim|3CV^|JO-8FaylM|71Xv4*kOx&du(vGqa?< uR-#^`l2Bf5a9V 1% +last 2 versions +Firefox ESR +not dead + +[browser-development] +last 1 chrome version +last 1 firefox version +last 1 safari version + +[isomorphic-production] +> 1% +last 2 versions +Firefox ESR +not dead +maintained node versions + +[isomorphic-development] +last 1 chrome version +last 1 firefox version +last 1 safari version +node 24 diff --git a/src/main/webapp/swagger/.claude/SKILL_USAGE_EXAMPLE.md b/src/main/webapp/swagger/.claude/SKILL_USAGE_EXAMPLE.md new file mode 100644 index 00000000..af1b863b --- /dev/null +++ b/src/main/webapp/swagger/.claude/SKILL_USAGE_EXAMPLE.md @@ -0,0 +1,565 @@ +# Skill Usage Example: Adding OAS 4.0 Support + +This document demonstrates how to use the `/add-oas-support` skill to add OpenAPI 4.0 support to Swagger UI. + +## Scenario + +You want to add support for OpenAPI Specification 4.0 (a hypothetical major version) to Swagger UI. OAS 4.0 includes: +- New `workflows` top-level field +- New `asyncAPI` authentication type +- Updated JSON Schema to Draft 2024 +- Enhanced callback syntax +- New `info.license.attribution` field + +## Step-by-Step Usage + +### 1. Start the Skill + +```bash +/add-oas-support --version 4.0 --type major +``` + +### 2. Answer Questions + +Claude will ask you questions about the new version: + +**Q: What is the exact version number?** +A: 4.0 + +**Q: Is it a major or minor version?** +A: Major (breaking changes from OAS 3.x) + +**Q: Does it use a new JSON Schema version?** +A: Yes, JSON Schema Draft 2024 + +**Q: What are the new top-level fields?** +A: `workflows` - defines reusable workflow definitions + +**Q: What features are added/removed/changed?** +A: +- Added: `workflows` object for workflow automation +- Added: `asyncAPI` authentication type +- Added: `info.license.attribution` field +- Changed: Callback syntax enhanced with workflow references +- Removed: Deprecated `x-` extension fields from OAS 3.0 + +**Q: Are there new authentication types?** +A: Yes, `asyncAPI` type for asynchronous authentication flows + +### 3. Claude Creates Plugin Structure + +Claude will execute: + +```bash +mkdir -p src/core/plugins/oas40/{auth-extensions,oas31-extensions,spec-extensions,components/auth,wrap-components} +``` + +### 4. Claude Generates Files + +#### 4a. Version Detection (src/core/plugins/oas40/fn.js) + +```javascript +/** + * @prettier + */ + +export const isOAS40 = (jsSpec) => { + const oasVersion = jsSpec.get("openapi") + return ( + typeof oasVersion === "string" && + /^4\.0\.(?:[1-9]\d*|0)$/.test(oasVersion) + ) +} + +export const createOnlyOAS40Selector = + (selector) => + (state, ...args) => + (system) => { + if (system.getSystem().specSelectors.isOAS40()) { + const selectedValue = selector(state, ...args) + return typeof selectedValue === "function" + ? selectedValue(system) + : selectedValue + } else { + return null + } + } + +// ... other factory functions +``` + +#### 4b. Main Plugin Export (src/core/plugins/oas40/index.js) + +```javascript +/** + * @prettier + */ + +import afterLoad from "./after-load.js" +import { + isOAS40, + createSystemSelector, + createOnlyOAS40Selector, + createOnlyOAS40SelectorWrapper, + createOnlyOAS40ComponentWrapper, +} from "./fn.js" + +import Workflows from "./components/workflows.jsx" +import AsyncAPIAuth from "./components/auth/async-api-auth.jsx" +import OAS40License from "./components/license.jsx" +// ... other imports + +const OpenAPI40Plugin = ({ fn }) => { + return { + fn: { + oas40: { + isOAS40, + createSystemSelector, + createOnlyOAS40Selector, + createOnlyOAS40SelectorWrapper, + createOnlyOAS40ComponentWrapper, + }, + }, + components: { + Workflows, + AsyncAPIAuth, + OAS40License, + }, + wrapComponents: { + // Wrap existing components + }, + statePlugins: { + spec: { + selectors: { + isOAS40: createSystemSelector(selectIsOAS40), + workflows: createOnlyOAS40Selector(selectWorkflows), + }, + wrapSelectors: { + isOAS31: isOAS31SelectorWrapper, + isOAS3: isOAS3SelectorWrapper, + }, + }, + auth: { + wrapSelectors: { + definitionsToAuthorize: definitionsToAuthorizeWrapper, + }, + }, + oas40: { + selectors: {}, + }, + }, + afterLoad, + } +} + +export default OpenAPI40Plugin +``` + +#### 4c. Workflows Component (src/core/plugins/oas40/components/workflows.jsx) + +```javascript +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" + +const Workflows = ({ specSelectors, getComponent }) => { + const workflows = specSelectors.workflows() + + if (!workflows || !workflows.size) { + return null + } + + const Operations = getComponent("operations", true) + + return ( +
+

Workflows

+
+

+ Reusable workflow definitions that can be referenced from operations. +

+
+ {workflows.entrySeq().map(([workflowName, workflow]) => ( +
+

{workflowName}

+

{workflow.get("description")}

+ {/* Render workflow steps */} +
+ ))} +
+ ) +} + +Workflows.propTypes = { + specSelectors: PropTypes.object.isRequired, + getComponent: PropTypes.func.isRequired, +} + +export default Workflows +``` + +#### 4d. AsyncAPI Auth Component (src/core/plugins/oas40/components/auth/async-api-auth.jsx) + +```javascript +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" + +const AsyncAPIAuth = ({ schema, name, getComponent, onChange, authorized }) => { + const authValue = authorized && authorized.getIn([name]) + const Input = getComponent("Input") + const Button = getComponent("Button") + + return ( +
+

AsyncAPI Authentication

+

{schema.get("description")}

+ onChange({ key: e.target.value })} + /> + +
+ ) +} + +AsyncAPIAuth.propTypes = { + schema: PropTypes.object.isRequired, + name: PropTypes.string.isRequired, + getComponent: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + authorized: PropTypes.object, +} + +export default AsyncAPIAuth +``` + +### 5. Claude Registers Plugin + +Updates `src/core/presets/apis/index.js`: + +```javascript +import OpenAPI40Plugin from "../../plugins/oas40/index.js" + +export default function PresetApis() { + return [ + BasePreset, + OpenAPI30Plugin, + JSONSchema202012Plugin, + JSONSchema202012SamplesPlugin, + OpenAPI31Plugin, + JSONSchema2024Plugin, // New JSON Schema version + JSONSchema2024SamplesPlugin, + OpenAPI40Plugin, // LAST - overrides all previous + ] +} +``` + +### 6. Claude Adds Tests + +#### Unit Test (test/unit/core/plugins/oas40/fn.js) + +```javascript +/** + * @prettier + */ + +import { fromJS } from "immutable" +import { isOAS40 } from "src/core/plugins/oas40/fn.js" + +describe("oas40 plugin - fn - isOAS40", () => { + it("should match OpenAPI 4.0.0", () => { + const spec = fromJS({ openapi: "4.0.0" }) + expect(isOAS40(spec)).toBe(true) + }) + + it("should match OpenAPI 4.0.15", () => { + const spec = fromJS({ openapi: "4.0.15" }) + expect(isOAS40(spec)).toBe(true) + }) + + it("should NOT match OpenAPI 4.0", () => { + const spec = fromJS({ openapi: "4.0" }) + expect(isOAS40(spec)).toBe(false) + }) + + it("should NOT match OpenAPI 3.1.0", () => { + const spec = fromJS({ openapi: "3.1.0" }) + expect(isOAS40(spec)).toBe(false) + }) +}) +``` + +#### E2E Test (test/e2e-cypress/e2e/features/oas40/workflows.cy.js) + +```javascript +/** + * @prettier + */ + +describe("OpenAPI 4.0 - Workflows", () => { + it("should render workflows section", () => { + cy.visit("/e2e-cypress/static/documents/oas40/petstore-workflows.yaml") + cy.get(".opblock-tag").contains("Workflows").should("exist") + }) + + it("should display workflow definitions", () => { + cy.visit("/e2e-cypress/static/documents/oas40/petstore-workflows.yaml") + cy.get(".opblock-workflow").should("have.length.greaterThan", 0) + }) +}) +``` + +### 7. Claude Updates Documentation + +Updates to `README.md`: + +```markdown +## Compatibility + +Swagger UI supports the following OpenAPI Specification versions: + +- OpenAPI 2.0 (Swagger) +- OpenAPI 3.0.x +- OpenAPI 3.1.x +- OpenAPI 4.0.x ⭐ NEW +``` + +Updates to `CLAUDE.md`: + +```markdown +### 26 Core Plugins + +- `oas3` - OpenAPI 3.0.x support +- `oas31` - OpenAPI 3.1.x support +- `oas40` - OpenAPI 4.0.x support (NEW) +``` + +### 8. Claude Runs Tests + +```bash +# Lint +npm run lint-errors + +# Unit tests +npm run test:unit + +# Build +npm run build + +# Artifact tests +npm run test:artifact + +# E2E tests +npm run cy:ci +``` + +### 9. Claude Creates Commit + +```bash +git add src/core/plugins/oas40/ +git add src/core/presets/apis/index.js +git add test/unit/core/plugins/oas40/ +git add test/e2e-cypress/e2e/features/oas40/ +git add README.md CLAUDE.md + +git commit -m "$(cat <<'EOF' +feat(oas40): add support for OpenAPI 4.0 + +Implement OpenAPI 4.0.x specification support with: +- Version detection and plugin architecture +- Workflows rendering for reusable workflow definitions +- AsyncAPI authentication type support +- JSON Schema Draft 2024 integration +- Enhanced callback syntax with workflow references +- License attribution field support + +Breaking changes from OAS 3.1: +- Removed deprecated x- extension fields +- Updated JSON Schema to Draft 2024 + +Includes comprehensive unit and E2E tests. + +Co-Authored-By: Claude Sonnet 4.5 +EOF +)" +``` + +### 10. Result + +You now have complete OpenAPI 4.0 support in Swagger UI: + +``` +src/core/plugins/oas40/ +├── index.js (367 lines) +├── fn.js (124 lines) +├── selectors.js (45 lines) +├── after-load.js (78 lines) +├── auth-extensions/ +│ └── wrap-selectors.js (32 lines) +├── oas31-extensions/ +│ └── fn.js (56 lines) +├── spec-extensions/ +│ ├── selectors.js (89 lines) +│ └── wrap-selectors.js (23 lines) +├── components/ +│ ├── workflows.jsx (156 lines) +│ ├── license.jsx (67 lines) +│ ├── version-pragma-filter.jsx (78 lines) +│ └── auth/ +│ └── async-api-auth.jsx (54 lines) +└── wrap-components/ + ├── info.jsx (12 lines) + └── license.jsx (12 lines) + +test/unit/core/plugins/oas40/ +├── fn.js (67 lines) +└── components/ + └── version-pragma-filter.jsx (45 lines) + +test/e2e-cypress/e2e/features/oas40/ +├── workflows.cy.js (34 lines) +└── async-api-auth.cy.js (28 lines) +``` + +**Total:** ~1,367 lines of code, fully tested and documented. + +## Benefits of Using the Skill + +### Without the Skill (Manual Implementation) + +**Estimated Time:** 40-60 hours + +**Challenges:** +- Understanding plugin architecture (4-6 hours) +- Studying OAS 3.1 patterns (3-4 hours) +- Creating file structure (1 hour) +- Implementing version detection (2 hours) +- Creating selector factories (4-6 hours) +- Implementing components (12-16 hours) +- Writing tests (8-12 hours) +- Debugging integration issues (6-8 hours) +- Documentation (2-3 hours) + +**Error-prone areas:** +- Plugin loading order +- Selector wrapping logic +- Component lifecycle +- Redux state management +- afterLoad hook timing + +### With the Skill (Guided Implementation) + +**Estimated Time:** 8-12 hours + +**Benefits:** +- Automated boilerplate generation +- Follows established patterns +- Guided step-by-step process +- Built-in error checking +- Comprehensive test coverage +- Documentation templates +- Best practices enforced + +**What the skill handles:** +- ✅ File structure creation +- ✅ Boilerplate code generation +- ✅ Pattern adherence +- ✅ Test scaffolding +- ✅ Documentation updates +- ✅ Build verification +- ✅ Commit message formatting + +## Customization Options + +The skill is flexible and can be customized per version: + +### For Minor Versions (e.g., 3.2) + +```bash +/add-oas-support --version 3.2 --type minor +``` + +Claude will: +- Create lighter plugin structure +- Reuse more from previous version +- Focus on incremental additions +- Skip breaking change handling +- Minimize component wrapping + +### For Major Versions (e.g., 5.0) + +```bash +/add-oas-support --version 5.0 --type major +``` + +Claude will: +- Create comprehensive plugin structure +- Implement extensive component wrapping +- Handle breaking changes +- Create new base components if needed +- Add deprecation warnings +- Update preset configurations + +## Troubleshooting + +### Skill Not Found + +``` +Error: Skill 'add-oas-support' not found +``` + +**Solution:** Ensure the skill file exists in `.claude/skills/add-oas-support.md` + +### Version Already Exists + +``` +Error: Plugin for OAS 4.0 already exists +``` + +**Solution:** Remove existing plugin or choose a different version + +### Build Failures + +``` +Error: Module not found +``` + +**Solution:** Check plugin registration in presets and import paths + +### Test Failures + +``` +Error: isOAS40 is not a function +``` + +**Solution:** Verify selector is properly exported and registered + +## Next Steps + +After the skill completes: + +1. **Test with real specs** - Use actual OAS 4.0 examples +2. **Review generated code** - Ensure it matches your requirements +3. **Add custom features** - Extend beyond the boilerplate +4. **Optimize performance** - Profile and optimize hot paths +5. **Submit PR** - Follow the PR template and guidelines + +## Additional Resources + +- **OAS 4.0 Spec:** https://spec.openapis.org/oas/v4.0.0 (hypothetical) +- **Plugin API:** `docs/customization/plugin-api.md` +- **CLAUDE.md:** Complete codebase guide +- **Skill Source:** `.claude/skills/add-oas-support.md` + +--- + +**Note:** This example uses hypothetical OAS 4.0 features for demonstration purposes. Adapt the skill usage to match the actual specification features of the version you're implementing. diff --git a/src/main/webapp/swagger/.claude/skills/README.md b/src/main/webapp/swagger/.claude/skills/README.md new file mode 100644 index 00000000..0d554806 --- /dev/null +++ b/src/main/webapp/swagger/.claude/skills/README.md @@ -0,0 +1,151 @@ +# Swagger UI Claude Skills + +This directory contains custom skills for working with the Swagger UI codebase in Claude Code. + +## Available Skills + +### `/add-oas-support` - Add OpenAPI Specification Version Support + +Comprehensive skill for adding support for a new OpenAPI Specification version to Swagger UI. + +**Usage:** +``` +/add-oas-support --version 4.0 --type major +/add-oas-support --version 3.2 --type minor +``` + +**Parameters:** +- `--version` (required): The OpenAPI version to add support for (e.g., "3.2", "4.0") +- `--type` (optional): Version type - "major" or "minor" (default: "minor") + +**Structure:** +The skill includes both a **Quick Reference** section at the top for experienced developers, and a **comprehensive guide** below for detailed implementation instructions. + +**What it does:** +1. **Analyzes the target OAS version specification using WebFetch** + - Fetches official spec from https://spec.openapis.org/ + - Systematically identifies new/modified/removed fields + - Maps specification changes to Swagger UI components + - Creates specification change document +2. Creates the plugin directory structure +3. Implements version detection logic +4. Creates selector factories and component wrappers +5. Implements new feature components based on spec analysis +6. Handles authentication changes +7. Registers plugin in presets +8. Adds unit and E2E tests +9. Updates documentation +10. Runs full test suite + +**Key Features:** +- ✅ **Quick Reference** section for rapid development +- ✅ Comprehensive specification analysis workflow using WebFetch +- ✅ Detailed mapping table from spec changes → components (15+ change types) +- ✅ Real examples from OAS 3.1 implementation (6 detailed examples) +- ✅ Iterative spec-driven development approach +- ✅ Component-by-component verification checklist +- ✅ Best practices for continuous spec reference +- ✅ WebFetch query templates for spec analysis +- ✅ Common pitfalls and solutions +- ✅ Pre-submit checklist + +**Based on:** +This skill follows the patterns established by the OAS 3.1 implementation (commit history analyzed from `src/core/plugins/oas31/`). + +**Key patterns:** +- Plugin-based architecture with Redux state management +- Selector factories for version-specific logic +- Component wrapping for conditional rendering +- afterLoad lifecycle hooks for function overrides +- Plugin loading order (new version loaded LAST) + +**Prerequisites:** +- Understanding of Swagger UI plugin architecture +- Access to the new OAS specification document +- All existing tests passing + +**Example workflow:** + +Adding OAS 4.0 support: +``` +# Start the skill +/add-oas-support --version 4.0 --type major + +# Claude will: +# 1. Ask about new features in OAS 4.0 +# 2. Create plugin directory structure +# 3. Generate boilerplate code +# 4. Guide through implementation +# 5. Add tests +# 6. Update documentation +# 7. Verify build +``` + +## Creating New Skills + +To create a new skill for Swagger UI: + +1. Create a markdown file in `.claude/skills/` +2. Add frontmatter with skill metadata: + ```yaml + --- + name: skill-name + description: Brief description + args: + param1: + description: "Parameter description" + required: true + type: string + --- + ``` +3. Write comprehensive instructions following the patterns in existing skills +4. Document common pitfalls and best practices +5. Include code templates with placeholders +6. Add to this README + +## Skill Development Guidelines + +When creating skills for Swagger UI: + +1. **Follow project conventions:** + - No semicolons + - Double quotes + - @prettier pragma in all new files + - .jsx extension for React components + +2. **Use the plugin architecture:** + - Don't modify core unnecessarily + - Follow established patterns + - Load new plugins at the end of presets + +3. **Include comprehensive tests:** + - Unit tests for logic + - Component tests for UI + - E2E tests for integration + +4. **Document thoroughly:** + - Update CLAUDE.md + - Update relevant docs + - Add inline JSDoc comments + +5. **Security first:** + - Use DOMPurify for HTML + - Validate all input + - Follow OWASP guidelines + +## Contributing + +To contribute new skills: + +1. Fork the repository +2. Create skill in `.claude/skills/` +3. Test thoroughly +4. Update this README +5. Submit pull request + +## Resources + +- **CLAUDE.md** - Comprehensive codebase guide +- **Plugin API** - `docs/customization/plugin-api.md` +- **Development Setup** - `docs/development/setting-up.md` +- **Contributing Guide** - https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md diff --git a/src/main/webapp/swagger/.claude/skills/add-oas-support.md b/src/main/webapp/swagger/.claude/skills/add-oas-support.md new file mode 100644 index 00000000..36062c30 --- /dev/null +++ b/src/main/webapp/swagger/.claude/skills/add-oas-support.md @@ -0,0 +1,2333 @@ +--- +name: add-oas-support +description: Add support for a new OpenAPI Specification version to Swagger UI +args: + version: + description: "OpenAPI version to add support for (e.g., 3.2, 4.0)" + required: true + type: string + type: + description: "Version type: 'major' for new major version, 'minor' for patch/minor" + required: false + type: string + default: "minor" +--- + +# Add OpenAPI Specification Version Support + +This skill guides you through adding support for a new OpenAPI Specification (OAS) version to Swagger UI, following the established architectural patterns from OAS 3.1 implementation. + +--- + +## 📌 Quick Reference + +> **New to this skill?** Skip to [Prerequisites](#prerequisites) for the full guide. +> **Already familiar?** Use this quick reference for rapid development. + +### 🚀 Quick Start + +```bash +# Major version (e.g., OAS 4.0) +/add-oas-support --version 4.0 --type major + +# Minor version (e.g., OAS 3.2) +/add-oas-support --version 3.2 --type minor +``` + +### 📋 Essential Checklist + +#### Phase 1: Specification Analysis ⭐ MOST IMPORTANT +- [ ] Access official spec at **https://spec.openapis.org/oas/v{VERSION}/** +- [ ] Use WebFetch to analyze spec systematically +- [ ] Create specification change document +- [ ] Map changes to components using [mapping table](#step-1d-map-specification-changes-to-swagger-ui-components) + +#### Phase 2: Implementation +- [ ] Create plugin directory structure +- [ ] Implement version detection (`isOAS{VERSION}`) +- [ ] Create selector factories +- [ ] Implement components for each spec change +- [ ] Wrap existing components if modified +- [ ] Register plugin in preset (LAST position) + +#### Phase 3: Testing & Documentation +- [ ] Add unit tests +- [ ] Add E2E tests with spec examples +- [ ] Update documentation +- [ ] Verify build & run full test suite + +### 🔍 WebFetch Queries for Spec Analysis + +```javascript +// 1. Fetch main spec differences +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "List all new top-level fields, modified fields, and removed fields compared to version {PREV_VERSION}" +) + +// 2. Analyze new feature +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "Describe the '{NEW_FIELD}' field: structure, type, purpose, required/optional, and provide examples" +) + +// 3. Check JSON Schema version +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "What JSON Schema version does this use? List changes from {PREV_JSON_SCHEMA_VERSION}" +) + +// 4. Security schemes +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "List all security scheme types, highlighting new or changed types" +) +``` + +### 🗺️ Spec Change → Component Mapping (Quick) + +| Spec Change | Component Action | File Location | +|-------------|------------------|---------------| +| **New top-level field (Object)** | Create new component | `components/{field}.jsx` | +| **New top-level field (String)** | Add to info or create display | `components/{field}.jsx` | +| **Modified Info object** | Wrap Info component | `wrap-components/info.jsx` | +| **New info subfield** | Create component + wrap Info | `components/info-{field}.jsx` | +| **New auth type** | Create auth component | `components/auth/{type}.jsx` | +| **Modified security** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | +| **New operation field** | Extend Operation/selector | `spec-extensions/selectors.js` | +| **JSON Schema keyword** | Create keyword component | `json-schema-{V}-extensions/` | +| **JSON Schema version** | Create entire new plugin | `plugins/json-schema-{V}/` | + +See [full mapping table with examples](#step-1d-map-specification-changes-to-swagger-ui-components) for detailed guidance. + +### 📝 Component Implementation Pattern + +**For each new feature:** + +1. **Check spec first:** + ```javascript + WebFetch(url, "Describe {field} structure, type, examples") + ``` + +2. **Create selector:** + ```javascript + // spec-extensions/selectors.js + export const selectNewField = createSelector( + (state) => state, + (state) => state.getIn(["spec", "json", "newField"]) + ) + ``` + +3. **Create component:** + ```javascript + // components/new-field.jsx + const NewField = ({ specSelectors, getComponent }) => { + const data = specSelectors.selectNewField() + if (!data) return null + return
{/* render based on spec structure */}
+ } + ``` + +4. **Register in plugin:** + ```javascript + // index.js + components: { NewField }, + statePlugins: { + spec: { + selectors: { + selectNewField: createOnlyOAS{V}Selector(selectNewField) + } + } + } + ``` + +5. **Add tests** (unit + E2E with spec examples) + +### ⚠️ Common Pitfalls + +1. ❌ **Guessing field structure** → ✅ Always check spec with WebFetch +2. ❌ **Forgetting @prettier pragma** → ✅ Add to all new files +3. ❌ **Wrong plugin load order** → ✅ New plugin LAST in preset +4. ❌ **Using semicolons** → ✅ No semicolons (project convention) +5. ❌ **Single quotes** → ✅ Use double quotes +6. ❌ **Skipping spec examples** → ✅ Use as test fixtures +7. ❌ **Hardcoded assumptions** → ✅ Verify everything in spec +8. ❌ **`props.Ori` in ComponentWrapper** → ✅ Use `props.originalComponent` (see Pattern 3) +9. ❌ **Copying entire Info component for minor version** → ✅ Use OpenAPIVersion wrapper + `getComponent("OAS{PREV}Info")` +10. ❌ **OAS{VERSION} logic in OAS{PREV} plugin** → ✅ Each version's logic lives in its own plugin +11. ❌ **`isOAS{PREV}` wrapper on minor version** → ✅ Only add if regex overlaps; minor bumps don't need it +12. ❌ **New HTTP method in core `validOperationMethods`** → ✅ Add to `OPERATION_METHODS` + wrap with `createOnlyOAS{VERSION}SelectorWrapper` +13. ❌ **Assuming new OAS meta-schema = new JSON Schema dialect** → ✅ Verify — OAS 3.2 still uses JSON Schema 2020-12 +14. ❌ **Inline version guard in wrap-components** → ✅ Always use `createOnlyOAS{VERSION}ComponentWrapper`; never write `(Original, system) => (props) => { if (...isOAS{VERSION}...) }` by hand — even expanding an existing guard (`isOAS31 || isOAS32`) is wrong; add dedicated wrap-components in the new plugin instead + +### ✅ Pre-Submit Checklist + +- [ ] All spec changes mapped to components +- [ ] All components reference spec in comments +- [ ] Tests use examples from spec +- [ ] Version detection regex correct +- [ ] Plugin loaded last in preset +- [ ] All tests passing (lint + unit + E2E) +- [ ] Build completes successfully +- [ ] Documentation updated +- [ ] No semicolons, double quotes everywhere +- [ ] @prettier pragma in all new files + +### 📚 Quick Links + +- **OAS Specs:** https://spec.openapis.org/ +- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/ +- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/ +- **JSON Schema:** https://json-schema.org/ +- **CLAUDE.md:** Complete codebase guide + +### 🔖 Full Guide Navigation + +Need detailed guidance? Jump to these sections: + +- **[Prerequisites](#prerequisites)** - Setup and requirements +- **[Architecture Overview](#architecture-overview)** - Plugin system explained +- **[Key Design Patterns](#key-design-patterns-from-oas-31)** - Code patterns from OAS 3.1 +- **[Step 1: Analyze Specification](#step-1-analyze-new-oas-version-specification)** - ⭐ Complete spec analysis workflow + - [1D: Mapping Table](#step-1d-map-specification-changes-to-swagger-ui-components) - 15+ spec change types + - [1E: Real Examples](#step-1e-examples-oas-31-specification-changes--components) - 6 detailed examples + - [1H: WebFetch Workflow](#step-1h-using-webfetch-to-analyze-specifications) - Spec analysis with WebFetch +- **[Step 2-17: Implementation](#step-2-create-plugin-directory-structure)** - Complete implementation steps +- **[Practical Workflow](#practical-workflow-from-spec-to-components)** - End-to-end example +- **[Best Practices](#best-practices-iterative-spec-driven-development)** - Spec-driven development +- **[Common Pitfalls](#common-pitfalls)** - What to avoid +- **[Final Checklist](#final-checklist)** - Pre-submission verification + +--- + +**Remember: The specification at https://spec.openapis.org/ is your source of truth!** + +--- + +## Prerequisites + +Before starting, ensure: +- You understand the Swagger UI plugin architecture +- You've read the CLAUDE.md guide +- You have the OAS specification document for the new version +- All tests pass: `npm test` + +## Architecture Overview + +Adding OAS version support involves: + +1. **Plugin Creation** - New plugin following established patterns +2. **Version Detection** - Regex-based version identifier +3. **Selector Factories** - Conditional logic for version-specific features +4. **Component Implementation** - New/wrapped components for rendering +5. **State Management** - Redux selectors/actions for new features +6. **Lifecycle Hooks** - afterLoad modifications +7. **Preset Registration** - Plugin loading order +8. **Testing** - Unit and E2E tests +9. **Documentation** - Update guides and README + +## Key Design Patterns (from OAS 3.1) + +### Pattern 1: Version Detection +```javascript +export const isOAS{VERSION} = (jsSpec) => { + const oasVersion = jsSpec.get("openapi") + return ( + typeof oasVersion === "string" && /^{MAJOR}\.{MINOR}\.(?:[1-9]\d*|0)$/.test(oasVersion) + ) +} +``` + +### Pattern 2: Selector Factories + +**createOnlyOAS{VERSION}Selector** - Features exclusive to this version: +```javascript +export const createOnlyOAS{VERSION}Selector = + (selector) => + (state, ...args) => + (system) => { + if (system.getSystem().specSelectors.isOAS{VERSION}()) { + const selectedValue = selector(state, ...args) + return typeof selectedValue === "function" + ? selectedValue(system) + : selectedValue + } else { + return null + } + } +``` + +**createOnlyOAS{VERSION}SelectorWrapper** - Override previous versions: +```javascript +export const createOnlyOAS{VERSION}SelectorWrapper = + (selector) => + (oriSelector, system) => + (state, ...args) => { + if (system.getSystem().specSelectors.isOAS{VERSION}()) { + const selectedValue = selector(state, ...args) + return typeof selectedValue === "function" + ? selectedValue(oriSelector, system) + : selectedValue + } else { + return oriSelector(...args) + } + } +``` + +### Pattern 3: Component Wrappers + +**⚠️ IMPORTANT: `originalComponent` prop name, not `Ori`** + +`createOnlyOAS{VERSION}ComponentWrapper` passes the original component as `originalComponent` in props (NOT `Ori` — that's the OAS3/OAS30ComponentWrapFactory convention). Use `const { originalComponent: Ori } = props` to access it. + +**Pattern A — Reuse previous version's component via getComponent:** +```javascript +const ComponentWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => { + const system = getSystem() + const OAS{PREV_VERSION}Component = system.getComponent("OAS{PREV_VERSION}Component", true) + return +}) +``` + +**Pattern B — Render original component with extra props (e.g. version badge):** +```javascript +// Use `originalComponent` (NOT `Ori`) — that's the prop name createOnlyOAS{VERSION}ComponentWrapper passes +const OpenAPIVersionWrapper = createOnlyOAS{VERSION}ComponentWrapper((props) => { + const { originalComponent: Ori } = props + return +}) +``` + +### Pattern 4: Function Wrapping +```javascript +export const wrapOAS{VERSION}Fn = (fn, system) => { + const { fn: systemFn, specSelectors } = system + return Object.fromEntries( + Object.entries(fn).map(([name, newImpl]) => { + const oriImpl = systemFn[name] + const impl = (...args) => + specSelectors.isOAS{VERSION}() + ? newImpl(...args) + : typeof oriImpl === "function" + ? oriImpl(...args) + : undefined + return [name, impl] + }) + ) +} +``` + +## Implementation Steps + +### Step 1: Analyze New OAS Version Specification + +**CRITICAL: Always start by reviewing the official specification at https://spec.openapis.org/** + +#### 1A. Access the Official Specification + +**Primary Resource:** https://spec.openapis.org/ + +**Available Versions:** +- OAS 2.0: https://spec.openapis.org/oas/v2.0/ +- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.3/ +- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0/ +- Future versions will follow the pattern: https://spec.openapis.org/oas/v{MAJOR}.{MINOR}.{PATCH}/ + +**What to download:** +1. The specification document (usually in HTML or Markdown format) +2. JSON Schema definitions (if available) +3. Example specification files +4. Change log or migration guide (if available) + +#### 1B. Systematic Specification Analysis + +Use the WebFetch tool to retrieve and analyze the specification: + +```bash +# Example for analyzing OAS 4.0 (hypothetical) +WebFetch("https://spec.openapis.org/oas/v4.0.0/", "List all new top-level fields, objects, and keywords introduced in this version compared to OAS 3.1") +``` + +**Read these sections carefully:** + +1. **Version Number Section** + - Confirm the exact version format (e.g., "4.0.0", "3.2.0") + - Note any version detection changes + +2. **OpenAPI Object (Root Level)** + - New top-level fields (e.g., `webhooks` in OAS 3.1) + - Modified existing fields + - Removed/deprecated fields + +3. **Info Object** + - New fields (e.g., `summary` in OAS 3.1) + - Changes to `license`, `contact`, etc. + +4. **Paths Object & Operations** + - New operation-level fields + - Changes to parameters, request bodies, responses + - New callback syntax or features + +5. **Components Object** + - New component types + - Schema changes (especially JSON Schema version) + - New security schemes + +6. **Security Object** + - New authentication types (e.g., `mutualTLS` in OAS 3.1) + - Changes to OAuth2 flows + - New security-related fields + +7. **Schema Object** + - JSON Schema version change (critical!) + - New keywords (e.g., `examples` vs `example`) + - Type system changes + +#### 1C. Create Specification Change Document + +Create a structured document listing all changes: + +**Template:** +```markdown +# OpenAPI {VERSION} Specification Analysis + +## Version Information +- Version: {MAJOR}.{MINOR}.{PATCH} +- Release Date: YYYY-MM-DD +- Previous Version: {PREVIOUS_VERSION} +- JSON Schema Version: Draft {VERSION} or {YEAR} + +## New Top-Level Fields +1. **`newField`** (Type: Object) + - Location: Root level + - Purpose: Description from spec + - Required: Yes/No + - Example from spec: {...} + - Swagger UI Impact: Needs new component in BaseLayout + +## Modified Existing Fields +1. **`info`** + - New subfields: `summary`, `newField` + - Changed behavior: Description + - Swagger UI Impact: Need to wrap Info component + +## New Operation-Level Features +1. **`newOperationField`** + - Purpose: Description + - Swagger UI Impact: Extend Operation component + +## New Authentication Types +1. **`newAuthType`** + - Type name: "newAuthType" + - Fields: {...} + - Swagger UI Impact: New auth component needed + +## JSON Schema Changes +- Version change: Draft 2020-12 → Draft 2024 +- New keywords: `keyword1`, `keyword2` +- Removed keywords: `oldKeyword` +- Swagger UI Impact: New json-schema plugin needed + +## Breaking Changes +1. Removed `x-deprecated-field` +2. Changed behavior of `existingField` +3. Required fields now enforced + +## Deprecated Features +1. `oldField` - Use `newField` instead +2. `oldAuthType` - Use `newAuthType` instead + +## Examples from Specification +- Link to example files +- Notable edge cases to test +``` + +#### 1D. Map Specification Changes to Swagger UI Components + +**CRITICAL MAPPING GUIDE:** Use this table to determine what components to create/modify: + +| Spec Change Type | Swagger UI Component Type | Location | Example from OAS 3.1 | +|-----------------|---------------------------|----------|---------------------| +| **New Top-Level Field (Object)** | New standalone component | `components/{feature-name}.jsx` | `webhooks` → `Webhooks.jsx` | +| **New Top-Level Field (String/Primitive)** | Add to existing layout component or create info component | `components/{field-name}.jsx` | `jsonSchemaDialect` → `JsonSchemaDialect.jsx` | +| **Modified Info Object** | Wrap Info component OR create OAS{VERSION}Info | `wrap-components/info.jsx` | `info.summary` → Wrapped InfoContainer | +| **New Info Subfield** | Create new component, render in Info | `components/info-{field}.jsx` | `info.license.identifier` → OAS31License | +| **Modified License/Contact** | Wrap component | `wrap-components/license.jsx` | `license.identifier` → Wrapped License | +| **New Authentication Type** | New auth component | `components/auth/{type}.jsx` | `mutualTLS` → `MutualTLSAuth.jsx` | +| **Modified Security Scheme** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | mutualTLS → `definitionsToAuthorize` wrapper | +| **New Operation Field** | Extend Operation or create plugin selector | `spec-extensions/selectors.js` | N/A in OAS 3.1 | +| **New Callback Feature** | Extend Callbacks component or wrap | `wrap-components/callbacks.jsx` | Enhanced in OAS 3.1 | +| **New Parameter Type** | Extend Parameters component | `components/parameters/` | N/A in OAS 3.1 | +| **New Response Feature** | Extend Responses component | `components/responses/` | N/A in OAS 3.1 | +| **New Media Type Feature** | Modify media-type component or fn | `oas{PREV}-extensions/fn.js` | File upload detection changes | +| **JSON Schema Keyword** | New keyword component | `json-schema-{VERSION}-extensions/components/keywords/` | `example` → `JSONSchema202012KeywordExample.jsx` | +| **JSON Schema Version Change** | Entire new plugin + samples plugin | `plugins/json-schema-{VERSION}/` | JSON Schema 2020-12 plugin | +| **Modified Schema Rendering** | Wrap schema component | `wrap-components/model.jsx` | Models → OAS31Models wrapper | +| **Version Detection Field** | Update VersionPragmaFilter | `components/version-pragma-filter.jsx` | Updated for isOAS31 | +| **Deprecated Field** | Remove or add deprecation warning | Component showing warning | N/A in OAS 3.1 | + +#### 1E. Examples: OAS 3.1 Specification Changes → Components + +**Example 1: `webhooks` Top-Level Field** + +**From Spec (OAS 3.1):** +```yaml +openapi: 3.1.0 +webhooks: + newPet: + post: + requestBody: + description: Information about a new pet + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + responses: + '200': + description: Return a 200 status +``` + +**Mapping Decision:** +- Type: New top-level field (Object containing operations) +- Location in spec: Root level, same structure as `paths` +- Swagger UI component: New standalone component +- File: `src/core/plugins/oas31/components/webhooks.jsx` +- Rendering: Reuses Operations component to render webhook operations +- Selector: `selectWebhooks` in `spec-extensions/selectors.js` +- Layout integration: Added to BaseLayout or StandaloneLayout + +**Example 2: `info.summary` Field** + +**From Spec (OAS 3.1):** +```yaml +info: + title: My API + summary: A brief summary of the API # NEW in OAS 3.1 + description: Detailed description... + version: 1.0.0 +``` + +**Mapping Decision:** +- Type: New subfield in existing Info object +- Location: `info.summary` +- Swagger UI component: Wrap existing Info component +- File: `src/core/plugins/oas31/wrap-components/info.jsx` + `src/core/plugins/oas31/components/info.jsx` +- Selector: `selectInfoSummary` (if needed) +- Rendering: Display summary above or below title + +**Example 3: `mutualTLS` Authentication Type** + +**From Spec (OAS 3.1):** +```yaml +components: + securitySchemes: + myMutualTLS: + type: mutualTLS # NEW in OAS 3.1 + description: Client certificate authentication +``` + +**Mapping Decision:** +- Type: New authentication scheme type +- Location: `components.securitySchemes[name].type` +- Swagger UI component: New auth component +- File: `src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx` +- Selector wrapper: `auth-extensions/wrap-selectors.js` → `definitionsToAuthorize` +- Rendering: Display in authorize modal with certificate upload UI + +**Example 4: `license.identifier` Field** + +**From Spec (OAS 3.1):** +```yaml +info: + license: + name: Apache 2.0 + identifier: Apache-2.0 # NEW in OAS 3.1 (SPDX ID) + url: https://www.apache.org/licenses/LICENSE-2.0.html +``` + +**Mapping Decision:** +- Type: New optional field in license object (alternative to url) +- Location: `info.license.identifier` +- Swagger UI component: Wrap License component + create selector +- File: `src/core/plugins/oas31/wrap-components/license.jsx` + selector in `spec-extensions/selectors.js` +- Logic: If `identifier` exists, construct URL from SPDX registry +- Rendering: Make license text a hyperlink to SPDX page + +**Example 5: JSON Schema 2020-12 Keywords** + +**From Spec (OAS 3.1):** +```yaml +# OAS 3.1 uses JSON Schema 2020-12 which includes: +components: + schemas: + Pet: + type: object + properties: + name: + type: string + example: Fluffy # Changed from 'examples' array in OAS 3.0 + xml: # Now a JSON Schema keyword, not OAS-specific + name: pet + externalDocs: # Now a JSON Schema keyword + url: https://example.com + discriminator: # Now a JSON Schema keyword + propertyName: petType +``` + +**Mapping Decision:** +- Type: JSON Schema version upgrade (Draft 7 → 2020-12) +- Location: Schema objects throughout spec +- Swagger UI components: Entire new plugin +- Files: + - `src/core/plugins/json-schema-2020-12/` (main plugin) + - `src/core/plugins/json-schema-2020-12-samples/` (sample generation) + - `src/core/plugins/json-schema-2020-12/components/keywords/example.jsx` + - `src/core/plugins/json-schema-2020-12/components/keywords/xml.jsx` + - `src/core/plugins/json-schema-2020-12/components/keywords/discriminator.jsx` + - `src/core/plugins/json-schema-2020-12/components/keywords/external-docs.jsx` +- Integration: OAS31 plugin extends JSON Schema 2020-12 keywords in `json-schema-2020-12-extensions/` + +**Example 6: `jsonSchemaDialect` Top-Level Field** + +**From Spec (OAS 3.1):** +```yaml +openapi: 3.1.0 +jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base # NEW in OAS 3.1 +``` + +**Mapping Decision:** +- Type: New top-level field (String/URI) +- Location: Root level +- Swagger UI component: Simple display component +- File: `src/core/plugins/oas31/components/json-schema-dialect.jsx` +- Selector: `selectJsonSchemaDialectField` in `spec-extensions/selectors.js` +- Rendering: Show in info section with warning if non-default + +#### 1F. Specification Analysis Checklist + +Use WebFetch and Read tools to systematically check: + +- [ ] **Accessed official spec at https://spec.openapis.org/** +- [ ] **Downloaded specification document** +- [ ] **Read version number section** +- [ ] **Analyzed OpenAPI Object (root level) changes** +- [ ] **Reviewed Info Object modifications** +- [ ] **Checked Paths/Operations changes** +- [ ] **Examined Components Object updates** +- [ ] **Identified Security Scheme changes** +- [ ] **Analyzed Schema Object / JSON Schema version** +- [ ] **Listed all new top-level fields** +- [ ] **Listed all modified existing fields** +- [ ] **Documented breaking changes** +- [ ] **Identified deprecated features** +- [ ] **Found example specifications** +- [ ] **Created specification change document** +- [ ] **Mapped changes to Swagger UI components using table above** +- [ ] **Prioritized implementation order** + +#### 1G. Questions to Answer During Analysis + +**Version Type:** +- Is this a major version (4.0) or minor version (3.2)? +- Are there breaking changes? +- Is backward compatibility maintained? + +**JSON Schema:** +- Does it use a new JSON Schema version? +- What new keywords are available? +- Are there removed/deprecated keywords? + +**Top-Level Changes:** +- What new top-level fields are added? +- Which existing fields have new subfields? +- Any removed top-level fields? + +**Operation Changes:** +- Are there new operation-level features? +- Changes to parameters, request bodies, responses? +- New callback or link syntax? + +**Security Changes:** +- What authentication types are new/changed? +- OAuth2 flow modifications? +- New security requirements? + +**Media Type Changes:** +- Are there new media type features? +- File upload handling changes? +- Encoding changes? + +**Component Mapping:** +- Which components need to be created from scratch? +- Which existing components need to be wrapped? +- What selectors are required? +- Are new plugins needed (e.g., for JSON Schema)? + +**Implementation Priority:** +- What's the critical path for basic rendering? +- Which features can be added incrementally? +- What has the highest user impact? + +### Step 1H: Using WebFetch to Analyze Specifications + +**Always use WebFetch tool to retrieve and analyze the specification systematically.** + +**Step-by-step WebFetch workflow:** + +1. **Fetch the specification landing page:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "Provide a summary of this OpenAPI Specification version, including links to the full specification document and any change logs or migration guides." +) +``` + +2. **Analyze the specification structure:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "List all top-level fields in the OpenAPI Object for this version. For each field, indicate if it is new, modified, or unchanged from version {PREVIOUS_VERSION}." +) +``` + +3. **Deep dive into new features:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "Describe the '{NEW_FIELD}' field in detail: its type, structure, purpose, whether it's required, and provide examples from the specification." +) +``` + +4. **Analyze security changes:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "List all security scheme types supported in this version. Highlight any new or changed security scheme types compared to {PREVIOUS_VERSION}." +) +``` + +5. **Check JSON Schema compatibility:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "What version of JSON Schema does this OpenAPI Specification version use? List any specific dialect or modifications to JSON Schema." +) +``` + +6. **Find example specifications:** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "Provide links to example OpenAPI specification files for this version, particularly examples that demonstrate new features." +) +``` + +**Real example from analyzing OAS 3.1:** + +```javascript +// 1. Initial analysis +WebFetch( + "https://spec.openapis.org/oas/v3.1.0/", + "List all new fields and features introduced in OpenAPI 3.1.0 compared to OpenAPI 3.0.3" +) + +// Response would include: +// - webhooks field (new top-level) +// - info.summary (new) +// - info.license.identifier (new) +// - jsonSchemaDialect (new top-level) +// - mutualTLS security scheme type (new) +// - JSON Schema 2020-12 (changed from Draft 7) + +// 2. Deep dive into webhooks +WebFetch( + "https://spec.openapis.org/oas/v3.1.0/", + "Explain the 'webhooks' field in detail: structure, purpose, and provide a complete example" +) + +// 3. Understand JSON Schema changes +WebFetch( + "https://spec.openapis.org/oas/v3.1.0/", + "What are the differences between JSON Schema Draft 7 (used in OAS 3.0) and JSON Schema 2020-12 (used in OAS 3.1) that affect schema definitions?" +) +``` + +**Pro tip:** Use multiple targeted queries rather than one broad query. This gives more precise information for each component you need to implement. + +### Step 2: Create Plugin Directory Structure + +**Directory:** `src/core/plugins/oas{VERSION_NUMBER}/` + +**Files to Create:** +``` +src/core/plugins/oas{VERSION_NUMBER}/ +├── index.js # Main plugin export +├── fn.js # Selector/function factories +├── selectors.js # Version-specific selectors (if needed) +├── after-load.js # Lifecycle hook +├── auth-extensions/ # Authentication features +│ └── wrap-selectors.js +├── oas{PREVIOUS_VERSION}-extensions/ # Extensions to previous version +│ └── fn.js +├── spec-extensions/ # Spec-level features +│ ├── selectors.js +│ └── wrap-selectors.js +├── components/ # New components +│ ├── version-pragma-filter.jsx +│ ├── {new-feature-1}.jsx +│ └── auth/ +│ └── {new-auth-type}.jsx +├── wrap-components/ # Component wrappers +│ ├── info.jsx +│ ├── license.jsx +│ └── {existing-component}.jsx +└── json-schema-{VERSION}-extensions/ # If new JSON Schema version + ├── fn.js + ├── components/keywords/ + └── wrap-components/keywords/ +``` + +**Create the directories:** +```bash +mkdir -p src/core/plugins/oas{VERSION_NUMBER}/{auth-extensions,oas{PREVIOUS_VERSION}-extensions,spec-extensions,components/auth,wrap-components} +``` + +### Step 3: Implement Version Detection (fn.js) + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/fn.js` + +**Template:** +```javascript +/** + * @prettier + */ + +/** + * Detects if a spec is OpenAPI {MAJOR}.{MINOR}.x + */ +export const isOAS{VERSION} = (jsSpec) => { + const oasVersion = jsSpec.get("openapi") + return ( + typeof oasVersion === "string" && + /^{MAJOR}\.{MINOR}\.(?:[1-9]\d*|0)$/.test(oasVersion) + ) +} + +/** + * Creates a selector that only returns a value for OAS {VERSION} specs + */ +export const createOnlyOAS{VERSION}Selector = + (selector) => + (state, ...args) => + (system) => { + if (system.getSystem().specSelectors.isOAS{VERSION}()) { + const selectedValue = selector(state, ...args) + return typeof selectedValue === "function" + ? selectedValue(system) + : selectedValue + } else { + return null + } + } + +/** + * Creates a selector wrapper that uses new impl for OAS {VERSION}, falls back to original + */ +export const createOnlyOAS{VERSION}SelectorWrapper = + (selector) => + (oriSelector, system) => + (state, ...args) => { + if (system.getSystem().specSelectors.isOAS{VERSION}()) { + const selectedValue = selector(state, ...args) + return typeof selectedValue === "function" + ? selectedValue(oriSelector, system) + : selectedValue + } else { + return oriSelector(...args) + } + } + +/** + * Creates a system-aware selector + */ +export const createSystemSelector = + (selector) => + (state, ...args) => + (system) => { + const selectedValue = selector(state, system, ...args) + return typeof selectedValue === "function" + ? selectedValue(system) + : selectedValue + } + +/** + * Creates a component wrapper that only renders for OAS {VERSION}. + * When active, passes `originalComponent` (the unwrapped original) and + * `getSystem` as extra props. Access the original via: + * const { originalComponent: Ori } = props + * NOT via `props.Ori` — that's the OAS3/OAS30ComponentWrapFactory convention. + */ +export const createOnlyOAS{VERSION}ComponentWrapper = + (Component) => (Original, system) => (props) => { + if (system.specSelectors.isOAS{VERSION}()) { + return ( + + ) + } + + return + } + +/** + * Wraps functions to conditionally use OAS {VERSION} implementations + */ +export const wrapOAS{VERSION}Fn = (fn, system) => { + const { fn: systemFn, specSelectors } = system + return Object.fromEntries( + Object.entries(fn).map(([name, newImpl]) => { + const oriImpl = systemFn[name] + const impl = (...args) => + specSelectors.isOAS{VERSION}() + ? newImpl(...args) + : typeof oriImpl === "function" + ? oriImpl(...args) + : undefined + return [name, impl] + }) + ) +} +``` + +### Step 4: Create Main Plugin Export (index.js) + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/index.js` + +**Template:** +```javascript +/** + * @prettier + */ + +import afterLoad from "./after-load.js" +import { + isOAS{VERSION}, + createSystemSelector, + createOnlyOAS{VERSION}Selector, + createOnlyOAS{VERSION}SelectorWrapper, + createOnlyOAS{VERSION}ComponentWrapper, +} from "./fn.js" + +// Import spec extensions +import * as specExtensionsSelectors from "./spec-extensions/selectors.js" +import * as specExtensionsWrapSelectors from "./spec-extensions/wrap-selectors.js" + +// Import auth extensions +import * as authExtensionsWrapSelectors from "./auth-extensions/wrap-selectors.js" + +// Import OAS{PREVIOUS_VERSION} extensions +import * as oas{PREVIOUS_VERSION}ExtensionsFn from "./oas{PREVIOUS_VERSION}-extensions/fn.js" + +// Import components +import VersionPragmaFilter from "./components/version-pragma-filter.jsx" +// Import new feature components here + +// Import wrap components +import InfoWrapper from "./wrap-components/info.jsx" +// Import other wrappers here + +/** + * OpenAPI {MAJOR}.{MINOR} Plugin + * + * Adds support for OpenAPI Specification {MAJOR}.{MINOR}.x + * + * This plugin should be loaded AFTER: + * - oas{PREVIOUS_VERSION} plugin + * - json-schema-{JSON_SCHEMA_VERSION} plugin (if applicable) + * + * It wraps and overrides components/selectors from previous versions. + */ +const OpenAPI{VERSION}Plugin = ({ fn }) => { + return { + fn: { + oas{VERSION_NUMBER}: { + isOAS{VERSION}, + createSystemSelector, + createOnlyOAS{VERSION}Selector, + createOnlyOAS{VERSION}SelectorWrapper, + createOnlyOAS{VERSION}ComponentWrapper, + }, + }, + components: { + // New components + OAS{VERSION}VersionPragmaFilter: VersionPragmaFilter, + // Add new feature components here + }, + wrapComponents: { + // Wrapped components + VersionPragmaFilter: (Ori, system) => + system.specSelectors.isOAS{VERSION}() + ? system.getComponent("OAS{VERSION}VersionPragmaFilter", true) + : Ori, + InfoContainer: InfoWrapper, + // Add other wrappers here + }, + statePlugins: { + spec: { + selectors: { + // Add version detection selector + isOAS{VERSION}: createSystemSelector(specExtensionsSelectors.selectIsOAS{VERSION}), + // Add new feature selectors here + }, + wrapSelectors: { + // Wrap previous version selectors if needed + ...specExtensionsWrapSelectors, + }, + }, + auth: { + wrapSelectors: { + // Add auth extensions if needed + ...authExtensionsWrapSelectors, + }, + }, + oas{VERSION_NUMBER}: { + selectors: { + // Plugin-specific selectors + }, + }, + }, + afterLoad, + } +} + +export default OpenAPI{VERSION}Plugin +``` + +### Step 5: Implement Spec Extensions + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/selectors.js` + +**Template:** +```javascript +/** + * @prettier + */ + +import { createSelector } from "reselect" +import { isOAS{VERSION} } from "../fn.js" + +/** + * Detects if the current spec is OAS {VERSION} + */ +export const selectIsOAS{VERSION} = (state, system) => () => { + const spec = system.specSelectors.specJson() + return isOAS{VERSION}(spec) +} + +// Add selectors for new OAS {VERSION} fields here +// Example: +// export const selectNewField = createSelector( +// (state) => state, +// (state) => { +// const spec = state.getIn(["spec", "json"]) +// return spec.get("newField") +// } +// ) +``` + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/wrap-selectors.js` + +**⚠️ Minor version: DON'T wrap `isOAS{PREV}` unless the regex actually matches both versions.** For example, OAS 3.1's `isOAS31` regex (`/^3\.1\./`) will never match `3.2.x`, so wrapping it to return `false` is dead code. Only add the `isOAS{PREV}` override if the previous version's detection regex would incorrectly match the new version. + +**Template:** +```javascript +/** + * @prettier + */ + +import { createOnlyOAS{VERSION}SelectorWrapper } from "../fn.js" + +// Ensure OAS {VERSION} specs are recognized as OAS 3.x (needed when major version number didn't change) +export const isOAS3 = + (oriSelector, system) => + (state, ...args) => { + const isOAS{VERSION} = system.specSelectors.isOAS{VERSION}() + return isOAS{VERSION} || oriSelector(...args) + } + +// ONLY add isOAS{PREV} wrapper if the previous version's regex could match this new version. +// For a minor version bump (e.g. 3.1 → 3.2), the previous regex won't match, so DON'T add this. +// export const isOAS{PREV} = createOnlyOAS{VERSION}SelectorWrapper((state) => () => false) +``` + +### Step 6: Create Version Pragma Filter Component + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx` + +**Template:** +```javascript +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" + +const OAS{VERSION}VersionPragmaFilter = ({ bypass, isSwagger2, isOAS3, isOAS{PREVIOUS_VERSION}, isOAS{VERSION} }) => { + // Handle version detection logic + const isAmbiguous = + (isSwagger2 && isOAS3) || + (isSwagger2 && isOAS{PREVIOUS_VERSION}) || + (isSwagger2 && isOAS{VERSION}) || + (isOAS3 && isOAS{PREVIOUS_VERSION}) || + (isOAS3 && isOAS{VERSION}) || + (isOAS{PREVIOUS_VERSION} && isOAS{VERSION}) + + const isMissing = !isSwagger2 && !isOAS3 && !isOAS{PREVIOUS_VERSION} && !isOAS{VERSION} + + if (bypass) { + return null + } + + if (isAmbiguous) { + return ( +
+
+
+

Unable to render this document, as it contains multiple OpenAPI version fields.

+
+
+
+ ) + } + + if (isMissing) { + return ( +
+
+
+

Unable to render this document, as it doesn't contain an OpenAPI version field.

+
+
+
+ ) + } + + return null +} + +OAS{VERSION}VersionPragmaFilter.propTypes = { + bypass: PropTypes.bool, + isSwagger2: PropTypes.bool.isRequired, + isOAS3: PropTypes.bool.isRequired, + isOAS{PREVIOUS_VERSION}: PropTypes.bool.isRequired, + isOAS{VERSION}: PropTypes.bool.isRequired, +} + +OAS{VERSION}VersionPragmaFilter.defaultProps = { + bypass: false, +} + +export default OAS{VERSION}VersionPragmaFilter +``` + +### Step 7: Implement New Feature Components + +For each new feature in the OAS specification: + +**Example: New Feature Component** +```javascript +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" + +const NewFeature = ({ getComponent, specSelectors }) => { + const newFeature = specSelectors.selectNewFeature() + + if (!newFeature || !newFeature.size) { + return null + } + + // Render the new feature + return ( +
+

New Feature

+ {/* Render logic here */} +
+ ) +} + +NewFeature.propTypes = { + specSelectors: PropTypes.object.isRequired, + getComponent: PropTypes.func.isRequired, +} + +export default NewFeature +``` + +### Step 8: Create Component Wrappers + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/wrap-components/info.jsx` + +**⚠️ Minor version (e.g. 3.2): don't create a new Info component.** If the Info object is identical to the previous version, reuse `OAS{PREV_VERSION}Info` via `getComponent` instead of copying the whole component. Only create a new Info component for major versions with significant structural changes. + +**Template (minor version — reuse previous Info):** +```javascript +/** + * @prettier + */ + +import React from "react" +import { createOnlyOAS{VERSION}ComponentWrapper } from "../fn.js" + +const InfoWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => { + const system = getSystem() + const OAS{PREV_VERSION}Info = system.getComponent("OAS{PREV_VERSION}Info", true) + return +}) + +export default InfoWrapper +``` + +**Also — OpenAPIVersion wrapper (minor version — change version badge only):** + +For minor versions where the only Info difference is the version badge, use the OpenAPIVersion wrapper pattern instead of wrapping InfoContainer at all: + +```javascript +// wrap-components/openapi-version.jsx +/** + * @prettier + */ +import React from "react" +import { createOnlyOAS{VERSION}ComponentWrapper } from "../fn.js" + +export default createOnlyOAS{VERSION}ComponentWrapper((props) => { + const { originalComponent: Ori } = props // NOT `Ori` from props directly — use `originalComponent` + return +}) +``` + +Then register it in index.js: +```javascript +wrapComponents: { + OpenAPIVersion: OpenAPIVersionWrapper, // changes the version badge shown in the Info header +} +``` + +### Step 9: Implement afterLoad Hook + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/after-load.js` + +**Template:** +```javascript +/** + * @prettier + */ + +import { wrapOAS{VERSION}Fn } from "./fn.js" + +/** + * afterLoad hook for OAS {VERSION} plugin + * + * This hook runs after all plugins are loaded and allows + * modification of the system's functions and behaviors. + */ +function afterLoad({ fn, getSystem }) { + const system = getSystem() + + // Override functions that differ in OAS {VERSION} + if (typeof fn.sampleFromSchema === "function") { + // Example: Wrap sample generation if JSON Schema version changed + // const wrappedFns = wrapOAS{VERSION}Fn({ + // sampleFromSchema: fn.jsonSchema{VERSION}.sampleFromSchema, + // }, system) + // Object.assign(this.fn, wrappedFns) + } + + // Override other functions as needed + // Example: File upload detection + // if (typeof fn.isFileUploadIntended === "function") { + // const wrappedFns = wrapOAS{VERSION}Fn({ + // isFileUploadIntended: makeIsFileUploadIntended(system), + // }, system) + // Object.assign(this.fn, wrappedFns) + // } +} + +export default afterLoad +``` + +### Step 10: Handle Authentication Changes + +If new authentication types are introduced: + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/auth/{auth-type}.jsx` + +**Template:** +```javascript +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" + +const NewAuthType = ({ schema, name, getComponent, onChange, authorized }) => { + const authValue = authorized && authorized.getIn([name]) + + const Input = getComponent("Input") + const Button = getComponent("Button") + + // Render auth UI + return ( +
+

{schema.get("description") || `${name} (${schema.get("type")})`}

+ {/* Auth UI here */} +
+ ) +} + +NewAuthType.propTypes = { + schema: PropTypes.object.isRequired, + name: PropTypes.string.isRequired, + getComponent: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + authorized: PropTypes.object, +} + +export default NewAuthType +``` + +**File:** `src/core/plugins/oas{VERSION_NUMBER}/auth-extensions/wrap-selectors.js` + +**Template:** +```javascript +/** + * @prettier + */ + +import { createOnlyOAS{VERSION}SelectorWrapper } from "../fn.js" +import { Map } from "immutable" + +/** + * Wraps definitionsToAuthorize to include new auth types + */ +export const definitionsToAuthorize = createOnlyOAS{VERSION}SelectorWrapper( + (state, system) => + (oriSelector) => { + const definitions = oriSelector() + const securityDefinitions = system.specSelectors.securityDefinitions() || Map() + + // Add new auth types to definitions + return definitions.map((definition) => { + const schema = securityDefinitions.get(definition.get("name")) + if (schema && schema.get("type") === "newAuthType") { + // Add new auth type logic + return definition.set("newAuthType", true) + } + return definition + }) + } +) +``` + +### Step 11: Register Plugin in Preset + +**File:** `src/core/presets/apis/index.js` + +**Add import:** +```javascript +import OpenAPI{VERSION}Plugin from "../../plugins/oas{VERSION_NUMBER}/index.js" +``` + +**Add to preset array (IMPORTANT: add at the end):** +```javascript +export default function PresetApis() { + return [ + BasePreset, + OpenAPI30Plugin, + // ... other plugins + OpenAPI{PREVIOUS_VERSION}Plugin, + OpenAPI{VERSION}Plugin, // Load LAST to override previous versions + ] +} +``` + +**Why load last?** +- Wrap-components override previous versions +- Wrap-selectors intercept earlier selectors +- afterLoad modifications apply to dependencies + +### Step 12: Add Unit Tests + +**Directory:** `test/unit/core/plugins/oas{VERSION_NUMBER}/` + +**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/fn.js` + +**Template:** +```javascript +/** + * @prettier + */ + +import { fromJS } from "immutable" +import { isOAS{VERSION} } from "src/core/plugins/oas{VERSION_NUMBER}/fn.js" + +describe("oas{VERSION_NUMBER} plugin - fn - isOAS{VERSION}", () => { + it("should match OpenAPI {MAJOR}.{MINOR}.0", () => { + const spec = fromJS({ openapi: "{MAJOR}.{MINOR}.0" }) + expect(isOAS{VERSION}(spec)).toBe(true) + }) + + it("should match OpenAPI {MAJOR}.{MINOR}.1", () => { + const spec = fromJS({ openapi: "{MAJOR}.{MINOR}.1" }) + expect(isOAS{VERSION}(spec)).toBe(true) + }) + + it("should match OpenAPI {MAJOR}.{MINOR}.25", () => { + const spec = fromJS({ openapi: "{MAJOR}.{MINOR}.25" }) + expect(isOAS{VERSION}(spec)).toBe(true) + }) + + it("should NOT match OpenAPI {MAJOR}.{MINOR}", () => { + const spec = fromJS({ openapi: "{MAJOR}.{MINOR}" }) + expect(isOAS{VERSION}(spec)).toBe(false) + }) + + it("should NOT match OpenAPI {MAJOR}.{MINOR}.01 (leading zero)", () => { + const spec = fromJS({ openapi: "{MAJOR}.{MINOR}.01" }) + expect(isOAS{VERSION}(spec)).toBe(false) + }) + + it("should NOT match OpenAPI {DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0", () => { + const spec = fromJS({ openapi: "{DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0" }) + expect(isOAS{VERSION}(spec)).toBe(false) + }) + + it("should NOT match swagger: 2.0", () => { + const spec = fromJS({ swagger: "2.0" }) + expect(isOAS{VERSION}(spec)).toBe(false) + }) + + it("should handle null spec", () => { + const spec = fromJS({}) + expect(isOAS{VERSION}(spec)).toBe(false) + }) +}) +``` + +**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx` + +**Template:** +```javascript +/** + * @prettier + */ + +import React from "react" +import { shallow } from "enzyme" +import OAS{VERSION}VersionPragmaFilter from "src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx" + +describe("OAS{VERSION}VersionPragmaFilter", () => { + it("should render nothing when bypass is true", () => { + const wrapper = shallow( + + ) + expect(wrapper.type()).toBe(null) + }) + + it("should render nothing when version is valid", () => { + const wrapper = shallow( + + ) + expect(wrapper.type()).toBe(null) + }) + + it("should render error when version is ambiguous", () => { + const wrapper = shallow( + + ) + expect(wrapper.find(".version-pragma__message--ambiguous")).toHaveLength(1) + }) + + it("should render error when version is missing", () => { + const wrapper = shallow( + + ) + expect(wrapper.find(".version-pragma__message--missing")).toHaveLength(1) + }) +}) +``` + +### Step 13: Add E2E Tests + +**Directory:** `test/e2e-cypress/e2e/features/oas{VERSION_NUMBER}/` + +**Create test spec file:** +```javascript +/** + * @prettier + */ + +describe("OpenAPI {MAJOR}.{MINOR} features", () => { + it("should detect OAS {VERSION} version", () => { + cy.visit("/oas{VERSION_NUMBER}-spec.html") + cy.get(".information-container .version").should("contain", "{MAJOR}.{MINOR}.0") + }) + + // Add tests for new features + it("should render new feature X", () => { + cy.visit("/oas{VERSION_NUMBER}-spec.html") + cy.get(".opblock-tag-section").should("contain", "New Feature") + }) +}) +``` + +**Add test fixtures:** +- Create sample OAS {VERSION} spec in `test/e2e-cypress/static/documents/oas{VERSION_NUMBER}/` +- Create HTML fixture in `test/e2e-cypress/static/` referencing the spec + +### Step 14: Update Documentation + +**Files to update:** + +1. **README.md** - Add OAS {VERSION} to supported versions +2. **CLAUDE.md** - Add plugin to list and update version compatibility +3. **docs/usage/version-detection.md** - Document new version detection +4. **package.json** - Update description if needed + +**Example README.md update:** +```markdown +### OpenAPI Specification Compatibility + +- **OpenAPI 2.0** (Swagger) +- **OpenAPI 3.0.x** +- **OpenAPI 3.1.x** +- **OpenAPI {MAJOR}.{MINOR}.x** ⭐ NEW +``` + +### Step 15: Verify Build + +**Run full build:** +```bash +npm run clean +npm run build +``` + +**Check dist/ output:** +- `dist/swagger-ui.js` - Should include new plugin +- `dist/swagger-ui.css` - Should include new styles (if any) +- Bundle size should be reasonable + +**Run artifact tests:** +```bash +npm run test:artifact +``` + +### Step 16: Run Full Test Suite + +```bash +npm run lint-errors # ESLint errors only +npm run test:unit # Jest unit tests +npm run cy:ci # Cypress E2E tests +``` + +**All tests must pass before submitting PR.** + +### Step 17: Create Pull Request + +**Commit message format:** +``` +feat(oas{VERSION_NUMBER}): add support for OpenAPI {MAJOR}.{MINOR} + +Implement OpenAPI {MAJOR}.{MINOR}.x specification support with: +- Version detection and plugin architecture +- New feature X rendering +- New authentication type Y support +- JSON Schema {VERSION} integration (if applicable) + +Closes #{ISSUE_NUMBER} +``` + +**PR checklist:** +- [ ] All tests passing +- [ ] New feature components implemented +- [ ] Unit tests added +- [ ] E2E tests added +- [ ] Documentation updated +- [ ] Build completes successfully +- [ ] No ESLint errors +- [ ] Follows existing code patterns + +## Common Pitfalls + +1. **Don't forget @prettier pragma** - Add to all new files +2. **Plugin loading order matters** - Load new plugin LAST in preset +3. **Use double quotes** - Project convention +4. **No semicolons** - Project convention +5. **Always use DOMPurify** - For any user-provided HTML +6. **Test with real specs** - Use actual OAS {VERSION} examples +7. **Don't modify core unnecessarily** - Use plugin architecture +8. **Version regex must be exact** - Follow pattern from OAS 3.1 +9. **Component wrappers render ``** - When not active version (handled by `createOnlyOAS{VERSION}ComponentWrapper` automatically) +10. **afterLoad runs after all plugins** - Safe to modify system +11. **`originalComponent` not `Ori`** - `createOnlyOAS{VERSION}ComponentWrapper` passes the original as `originalComponent` prop. Use `const { originalComponent: Ori } = props`. The `Ori` name comes from `OAS30ComponentWrapFactory` which uses a different signature. +12. **Don't copy the entire Info component for minor versions** - Use the OpenAPIVersion wrapper to change the version badge, and reuse the previous version's Info via `getComponent("OAS{PREV}Info", true)` instead of copying. +13. **Don't add version-specific logic to previous version's plugin** - OAS32 logic belongs in the OAS32 plugin, not in OAS31 plugin files (e.g. don't add `isOAS32` checks to `oas31/wrap-components/license.jsx`). +20. **Always use `createOnlyOAS{VERSION}ComponentWrapper` in wrap-components — never inline the version guard** - Each wrap-component in a plugin should use the factory (`createOnlyOAS{VERSION}ComponentWrapper`), not a hand-written `(Original, system) => (props) => { if (system.specSelectors.isOAS{VERSION}()) ... }`. When a later version (OAS32) also needs to reuse the same OAS31 component, it gets its own dedicated wrap-component in the OAS32 plugin — don't expand the guard to `isOAS31 || isOAS32` in the OAS31 file. The OAS31 wrappers for contact/license should use `createOnlyOAS31ComponentWrapper` and nothing else; OAS32 contact/license wrappers live in `oas32/wrap-components/` and handle the OAS32 case. +14. **Don't add `isOAS{PREV}` wrap-selector unless the regex actually overlaps** - For minor versions, the previous version's regex already won't match (e.g. OAS31's `/^3\.1\./` won't match `3.2.x`). Adding the wrapper is dead code. +15. **New HTTP methods: use `OPERATION_METHODS` in `spec/selectors.js`, not `operationsWithRootInherited` wrapper** - Adding the method to `OPERATION_METHODS` makes the core `operations` selector collect those ops. The `validOperationMethods` wrapper (guarded by `createOnlyOAS{VERSION}SelectorWrapper`) then controls whether the UI renders them. No need for an `operationsWithRootInherited` wrapper. +16. **Don't add new HTTP methods to the core `validOperationMethods` constant** - Adding `"query"` to the base constant in `spec/selectors.js` affects ALL OAS versions. Instead, add it only via `createOnlyOAS{VERSION}SelectorWrapper` in your plugin's `spec-extensions/wrap-selectors.js`. +17. **Don't create selectors only used in tests** - Selectors like `selectHasQueryOperations` that are never called from production code should not exist. Remove them. +18. **OAS meta-schema URL ≠ new JSON Schema dialect** - The URL `https://spec.openapis.org/oas/3.2/schema/...` is the OAS 3.2 document structure schema, NOT a new JSON Schema version. OAS 3.2 uses JSON Schema 2020-12, the same as OAS 3.1. Don't list "new JSON Schema version" as a feature unless it actually changes. +19. **Verify "not yet implemented" feature list against previous version** - Features like `pathItems in Components` were already in OAS 3.1, not new in 3.2. Check what's actually new before listing it. + +## JSON Schema Version Changes + +**⚠️ First, verify whether the JSON Schema version actually changed.** The OAS meta-schema URL (e.g. `https://spec.openapis.org/oas/3.2/schema/...`) describes the OAS document structure — it is NOT a new JSON Schema dialect. OAS 3.2 uses JSON Schema 2020-12, the same as OAS 3.1. Only create a new `json-schema-{VERSION}` plugin if the actual JSON Schema dialect changed (as it did from OAS 3.0 Draft-07 → OAS 3.1 JSON Schema 2020-12). + +If the new OAS version uses a different JSON Schema version: + +1. **Create json-schema-{VERSION} plugin** (separate from OAS plugin) +2. **Implement keyword components** for new schema features +3. **Update sample generation** logic +4. **Add schema validation** support +5. **Load json-schema-{VERSION} plugin BEFORE oas{VERSION_NUMBER}** in preset + +Example from OAS 3.1 using JSON Schema 2020-12: +- `src/core/plugins/json-schema-2020-12/` - Main plugin +- `src/core/plugins/json-schema-2020-12-samples/` - Sample generation +- Loaded before `oas31` plugin in preset + +## Major vs Minor Version Considerations + +### Major Version (e.g., 4.0) + +**Likely includes:** +- Breaking changes from previous major version +- New top-level fields +- Removed/deprecated features +- Possibly new JSON Schema version +- New authentication paradigms +- Restructured spec format + +**Implementation approach:** +- Create completely separate plugin +- May need to create new base components +- Extensive wrapping of previous version components +- Significant selector overrides +- New preset configuration options + +### Minor Version (e.g., 3.2) + +**Likely includes:** +- Backward-compatible additions +- New optional fields +- Enhanced existing features +- Same JSON Schema version (verify before assuming it changed) +- Incremental improvements + +**Implementation approach:** +- Lighter plugin with focused additions +- Fewer component wrappers needed +- Selective selector additions +- Reuse most of previous version logic via `getComponent("OAS{PREV}...", true)` +- Simpler afterLoad modifications + +**Key decisions for minor versions (lessons from OAS 3.2):** + +1. **Version badge only changed?** Use `OpenAPIVersion` wrapper + reuse `OAS{PREV}Info` — don't create a new Info component. +2. **New HTTP method (e.g. QUERY)?** Add it to `OPERATION_METHODS` in `src/core/plugins/spec/selectors.js` AND add it to `validOperationMethods` via `createOnlyOAS{VERSION}SelectorWrapper`. Don't add it to the core `validOperationMethods` constant (affects all versions). +3. **`isOAS{PREV}` wrapper needed?** Only if the previous regex also matches the new version string. Minor version bumps (3.1 → 3.2) don't need it. +4. **JSON Schema version comment?** Verify it actually changed. OAS 3.2 uses JSON Schema 2020-12, the same as OAS 3.1. The new OAS meta-schema URL (`https://spec.openapis.org/oas/3.2/schema/...`) describes OAS document structure, not a new JSON Schema dialect. +5. **"Not yet implemented" list?** Double-check each item against the *previous* version's changelog — some may already be implemented. + +## Example: Adding OAS 4.0 (Major) + +**Version detection:** +```javascript +export const isOAS40 = (jsSpec) => { + const oasVersion = jsSpec.get("openapi") + return ( + typeof oasVersion === "string" && /^4\.0\.(?:[1-9]\d*|0)$/.test(oasVersion) + ) +} +``` + +**Directory:** `src/core/plugins/oas40/` + +**Wrap previous version:** +```javascript +// spec-extensions/wrap-selectors.js +export const isOAS31 = createOnlyOAS40SelectorWrapper((state) => () => false) +export const isOAS3 = createOnlyOAS40SelectorWrapper((state) => () => false) +``` + +**Register in preset:** +```javascript +// src/core/presets/apis/index.js +export default function PresetApis() { + return [ + BasePreset, + OpenAPI30Plugin, + OpenAPI31Plugin, + OpenAPI40Plugin, // LAST + ] +} +``` + +## Example: Adding OAS 3.2 (Minor) + +**Version detection:** +```javascript +export const isOAS32 = (jsSpec) => { + const oasVersion = jsSpec.get("openapi") + return ( + typeof oasVersion === "string" && /^3\.2\.(?:[1-9]\d*|0)$/.test(oasVersion) + ) +} +``` + +**Directory:** `src/core/plugins/oas32/` + +**Lighter component wrapping — OAS 3.2 specific patterns:** + +```javascript +// wrap-components/openapi-version.jsx — change the version badge only +// Use `originalComponent` (NOT `Ori`) — that's what createOnlyOAS32ComponentWrapper passes +export default createOnlyOAS32ComponentWrapper((props) => { + const { originalComponent: Ori } = props + return +}) + +// wrap-components/info.jsx — reuse OAS31Info, don't create a new one +export default createOnlyOAS32ComponentWrapper(({ getSystem }) => { + const system = getSystem() + const OAS31Info = system.getComponent("OAS31Info", true) + return +}) + +// wrap-components/contact.jsx and license.jsx — same pattern (OAS32 logic belongs HERE, not in OAS31) +export default createOnlyOAS32ComponentWrapper((props) => { + const { getSystem } = props + const system = getSystem() + const OAS31Contact = system.getComponent("OAS31Contact", true) + return +}) +``` + +**New HTTP method (QUERY) — two-part approach:** + +Part 1: Add to `OPERATION_METHODS` in `src/core/plugins/spec/selectors.js` so the `operations` selector collects QUERY ops: +```javascript +// spec/selectors.js +export const OPERATION_METHODS = [ + "get", "put", "post", "delete", "options", "head", "patch", "trace", "query", +] +``` + +Part 2: Add to `validOperationMethods` via `createOnlyOAS32SelectorWrapper` so the UI only renders them for OAS 3.2: +```javascript +// oas32/spec-extensions/wrap-selectors.js +export const validOperationMethods = createOnlyOAS32SelectorWrapper( + () => (oriSelector, system) => system.oas32Selectors.validOperationMethods() +) + +// oas32/selectors.js +export const validOperationMethods = () => [ + "get", "put", "post", "delete", "options", "head", "patch", "trace", "query", +] +``` + +Do NOT add `"query"` to the core `validOperationMethods` constant — that would affect all versions. + +## Final Checklist + +Before marking the task as complete: + +- [ ] Plugin created in `src/core/plugins/oas{VERSION_NUMBER}/` +- [ ] Version detection function implemented and tested +- [ ] Selector factories created +- [ ] New feature components implemented +- [ ] Component wrappers created for modified components +- [ ] Spec extension selectors implemented +- [ ] Auth extensions implemented (if new auth types) +- [ ] afterLoad hook implemented +- [ ] Plugin registered in preset (LAST position) +- [ ] Unit tests added and passing +- [ ] E2E tests added and passing +- [ ] Documentation updated (README, CLAUDE.md, docs/) +- [ ] Build completes successfully +- [ ] Artifact tests pass +- [ ] No ESLint errors +- [ ] Code follows project conventions (no semicolons, double quotes, @prettier pragma) +- [ ] All security considerations addressed (DOMPurify, input validation) +- [ ] PR created with proper commit message format + +## Practical Workflow: From Spec to Components + +This section demonstrates the complete workflow from specification analysis to component implementation. + +### Workflow Example: Adding a Hypothetical `workflows` Field + +**Scenario:** OAS 4.0 introduces a new `workflows` top-level field for defining reusable workflow definitions. + +#### Phase 1: Specification Research + +**Step 1: Fetch the spec section** +```javascript +WebFetch( + "https://spec.openapis.org/oas/v4.0.0/", + "Describe the 'workflows' field: its structure, purpose, whether it's required, and provide a complete example from the specification." +) +``` + +**Step 2: Analyze the structure** +```javascript +// Response analysis: +// - Type: Object (Map[string, Workflow Object]) +// - Location: Root level (sibling to 'paths') +// - Required: No (optional) +// - Structure: Similar to paths, but defines reusable workflows +// - Example: +workflows: + onNewUser: + steps: + - operationRef: '#/paths/~1users/post' + - operationRef: '#/paths/~1emails~1welcome/post' +``` + +**Step 3: Map to component type** +Using the mapping table from Step 1D: +- Change type: New top-level field (Object) +- Component type: New standalone component +- Similar to: `webhooks` in OAS 3.1 + +#### Phase 2: Component Design + +**File structure decision:** +``` +src/core/plugins/oas40/ +├── components/ +│ └── workflows.jsx # Main component +└── spec-extensions/ + └── selectors.js # Add selectWorkflows +``` + +**Component responsibilities:** +1. Select workflows from spec +2. Render workflow list +3. Display workflow steps +4. Link to referenced operations + +#### Phase 3: Implementation + +**Step 1: Create selector** +```javascript +// src/core/plugins/oas40/spec-extensions/selectors.js + +export const selectWorkflows = createSelector( + (state) => state, + (state) => { + const spec = state.getIn(["spec", "json"]) + return spec.get("workflows") || Map() + } +) +``` + +**Step 2: Create component** +```javascript +// src/core/plugins/oas40/components/workflows.jsx + +/** + * @prettier + */ + +import React from "react" +import PropTypes from "prop-types" +import ImPropTypes from "react-immutable-proptypes" + +const Workflows = ({ specSelectors, getComponent }) => { + const workflows = specSelectors.workflows() + + if (!workflows || !workflows.size) { + return null + } + + const Collapse = getComponent("Collapse") + + return ( +
+

Workflows

+
+

+ Reusable workflow definitions that can be referenced from operations. +

+
+ {workflows.entrySeq().map(([workflowName, workflow]) => ( +
+ +
+

{workflowName}

+ {workflow.get("description") && ( +
+ {workflow.get("description")} +
+ )} +
+
+ {workflow.get("steps") && ( +
    + {workflow.get("steps").map((step, idx) => ( +
  • + {step.get("operationRef") || step.get("workflowRef")} +
  • + ))} +
+ )} +
+
+
+ ))} +
+ ) +} + +Workflows.propTypes = { + specSelectors: PropTypes.shape({ + workflows: PropTypes.func.isRequired, + }).isRequired, + getComponent: PropTypes.func.isRequired, +} + +export default Workflows +``` + +**Step 3: Register in plugin** +```javascript +// src/core/plugins/oas40/index.js + +import Workflows from "./components/workflows.jsx" +import { selectWorkflows } from "./spec-extensions/selectors.js" + +const OpenAPI40Plugin = ({ fn }) => { + return { + components: { + Workflows, + }, + statePlugins: { + spec: { + selectors: { + workflows: createOnlyOAS40Selector(selectWorkflows), + }, + }, + }, + } +} +``` + +**Step 4: Add to layout** +```javascript +// Modify layout to include Workflows component +// This would be done in BaseLayout or a wrapper +``` + +#### Phase 4: Testing + +**Step 1: Create test spec** +```yaml +# test/e2e-cypress/static/documents/oas40/workflows-example.yaml +openapi: 4.0.0 +info: + title: Workflows API + version: 1.0.0 +workflows: + onNewUser: + description: Workflow triggered when a new user is created + steps: + - operationRef: '#/paths/~1users/post' + - operationRef: '#/paths/~1emails~1welcome/post' +paths: + /users: + post: + summary: Create user + # ... +``` + +**Step 2: Create E2E test** +```javascript +// test/e2e-cypress/e2e/features/oas40/workflows.cy.js + +describe("OAS 4.0 - Workflows", () => { + beforeEach(() => { + cy.visit("/e2e-cypress/static/documents/oas40/workflows-example.yaml") + }) + + it("should render workflows section", () => { + cy.get(".opblock-tag").contains("Workflows").should("exist") + }) + + it("should display workflow definitions", () => { + cy.get(".opblock-workflow").should("have.length.greaterThan", 0) + }) + + it("should show workflow steps", () => { + cy.get(".opblock-workflow-steps ul li").should("exist") + }) +}) +``` + +**Step 3: Create unit test** +```javascript +// test/unit/core/plugins/oas40/components/workflows.jsx + +import React from "react" +import { shallow } from "enzyme" +import { fromJS } from "immutable" +import Workflows from "src/core/plugins/oas40/components/workflows.jsx" + +describe("Workflows component", () => { + it("should render workflows from spec", () => { + const mockWorkflows = fromJS({ + onNewUser: { + description: "New user workflow", + steps: [ + { operationRef: "#/paths/~1users/post" } + ] + } + }) + + const props = { + specSelectors: { + workflows: () => mockWorkflows + }, + getComponent: (name) => { + if (name === "Collapse") { + return ({ children }) =>
{children}
+ } + } + } + + const wrapper = shallow() + expect(wrapper.find(".opblock-workflow")).toHaveLength(1) + }) + + it("should render nothing when no workflows", () => { + const props = { + specSelectors: { + workflows: () => fromJS({}) + }, + getComponent: () => null + } + + const wrapper = shallow() + expect(wrapper.type()).toBe(null) + }) +}) +``` + +### Summary: Spec → Component Mapping Checklist + +For each new feature in the specification: + +- [ ] **Analyze spec using WebFetch** + - [ ] Understand structure and purpose + - [ ] Get examples from spec + - [ ] Identify data type and location + +- [ ] **Map to component type** (using Step 1D table) + - [ ] Determine if new component or wrapper needed + - [ ] Identify similar existing components + - [ ] Plan component hierarchy + +- [ ] **Create selector** + - [ ] Extract data from spec + - [ ] Use appropriate selector factory + - [ ] Add to spec-extensions/selectors.js + +- [ ] **Implement component** + - [ ] Follow existing patterns + - [ ] Use getComponent for sub-components + - [ ] Add PropTypes validation + - [ ] Include @prettier pragma + +- [ ] **Register in plugin** + - [ ] Add to components export + - [ ] Register selector in statePlugins + - [ ] Add to layout if top-level feature + +- [ ] **Create tests** + - [ ] Unit tests for component + - [ ] Unit tests for selector + - [ ] E2E tests with example spec + - [ ] Test edge cases (missing data, etc.) + +- [ ] **Verify with real spec** + - [ ] Test with example from official spec + - [ ] Test edge cases mentioned in spec + - [ ] Verify rendering matches expected behavior + +## Resources + +- **OAS Specification:** https://spec.openapis.org/ +- **OAS 2.0:** https://spec.openapis.org/oas/v2.0/ +- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/ +- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/ +- **JSON Schema:** https://json-schema.org/ +- **Plugin API Docs:** `docs/customization/plugin-api.md` +- **OAS 3.1 Reference:** `src/core/plugins/oas31/` +- **Version Detection:** `src/core/plugins/versions/` +- **CLAUDE.md:** Complete codebase guide + +## Best Practices: Iterative Spec-Driven Development + +### Continuous Specification Reference + +**NEVER implement a feature without checking the spec first.** The specification is your source of truth. + +#### During Initial Planning +1. Read the entire specification document +2. Create your component mapping document +3. Prioritize features by importance and dependency + +#### During Implementation +**For each component:** + +1. **Before writing code:** + ```javascript + WebFetch( + "https://spec.openapis.org/oas/v{VERSION}/", + "Provide the complete specification for the '{FIELD_NAME}' field, including all properties, data types, constraints, and examples." + ) + ``` + +2. **While writing the selector:** + - Verify the exact field path in the spec + - Check if field is required or optional + - Confirm data type (string, object, array, etc.) + - Note any default values + +3. **While writing the component:** + - Reference spec examples for rendering approach + - Implement all specified subfields + - Handle edge cases mentioned in spec + - Follow spec's field naming exactly + +4. **After writing tests:** + - Use spec examples as test fixtures + - Test all scenarios mentioned in spec + - Verify behavior matches spec descriptions + +#### Common Mistakes to Avoid + +❌ **DON'T:** +- Guess field structure without checking spec +- Assume field behavior from field name +- Skip optional fields thinking they're unimportant +- Implement based on previous version without checking changes +- Use hardcoded strings without verifying in spec + +✅ **DO:** +- Read spec section before each component +- Verify field paths with WebFetch +- Check spec examples for edge cases +- Confirm data types and constraints +- Reference spec in code comments + +#### Example: Spec-Driven Implementation + +**Bad approach (guessing):** +```javascript +// ❌ Guessing the structure +const workflows = spec.get("workflows") +return workflows.map(w => w.name) // Assumes 'name' exists +``` + +**Good approach (spec-driven):** +```javascript +// ✅ First check the spec: +// WebFetch result shows workflows is a Map[string, Workflow Object] +// Each workflow has: description, steps (array), parameters (optional) + +// Then implement correctly: +const workflows = spec.get("workflows") // Map[string, Workflow Object] +if (!workflows || !workflows.size) return null + +return workflows.entrySeq().map(([workflowName, workflowObject]) => { + // workflowName is the key, workflowObject contains: description, steps, etc. + const description = workflowObject.get("description") + const steps = workflowObject.get("steps") || List() + // ... +}) +``` + +### Verification Checklist Per Component + +Before marking a component complete, verify against spec: + +- [ ] **Field location matches spec exactly** (path in spec tree) +- [ ] **Data type implemented correctly** (string, object, array, etc.) +- [ ] **Required fields are handled** (error if missing vs optional) +- [ ] **Optional fields have defaults** (as specified in spec) +- [ ] **All subfields are rendered** (no fields missed) +- [ ] **Constraints are enforced** (min/max, enums, formats) +- [ ] **Examples from spec render correctly** (visual verification) +- [ ] **Edge cases are handled** (empty, null, malformed) +- [ ] **Field descriptions match spec** (for documentation) +- [ ] **Cross-references work** ($ref, operationRef, etc.) + +### Documentation Trail + +Leave a trail connecting your code to the spec: + +```javascript +/** + * @prettier + */ + +/** + * Workflows Component + * + * Renders the 'workflows' field from OpenAPI 4.0 specification. + * + * Spec reference: https://spec.openapis.org/oas/v4.0.0/#workflows-object + * + * Structure (from spec): + * workflows: + * {workflowName}: + * description: string (optional) + * steps: array of Step Objects (required) + * parameters: Map[string, Parameter] (optional) + * + * This component renders a list of workflow definitions, showing + * workflow steps and their operation references. + */ +const Workflows = ({ specSelectors, getComponent }) => { + // Implementation referencing spec structure +} +``` + +### Progressive Implementation Strategy + +Implement features in order of dependency and spec structure: + +**Phase 1: Core Fields (from spec root)** +1. Version detection (always first) +2. Top-level required fields +3. Top-level optional fields with high usage + +**Phase 2: Info Object Enhancements** +1. New info fields +2. Modified license/contact fields +3. Extended metadata fields + +**Phase 3: Component Object Extensions** +1. New component types +2. Schema keyword changes (if JSON Schema version changed) +3. Security scheme additions + +**Phase 4: Operation-Level Features** +1. New operation fields +2. Parameter enhancements +3. Request/response modifications +4. Callback/link changes + +**Phase 5: Advanced Features** +1. Complex interactions (workflows, callbacks, links) +2. Conditional rendering +3. Advanced security features + +### Spec Change Impact Analysis + +Before implementing, analyze the impact: + +| Spec Change | Swagger UI Impact | Implementation Effort | User Impact | +|-------------|-------------------|----------------------|-------------| +| New top-level field | New component + layout change | High | High | +| New info subfield | Wrap or extend Info | Medium | Medium | +| New auth type | New auth component | Medium | High | +| New schema keyword | Keyword component | Low-Medium | Low | +| Field description change | Documentation only | Low | Low | +| Deprecated field | Warning message | Low | Medium | +| Breaking change | Major refactor | High | High | + +Prioritize high user impact changes first. + +## Questions to Answer During Implementation + +### Before Starting +1. What is the exact version number? (e.g., 3.2, 4.0) +2. Have I read the complete specification at https://spec.openapis.org/? +3. Is it a major or minor version change? +4. What is the migration guide URL? + +### Specification Analysis +5. Does it use a new JSON Schema version? +6. What are ALL the new top-level fields? +7. What are ALL the modified existing fields? +8. What features are deprecated or removed? + +### Component Planning +9. Which components need to be created from scratch? +10. Which existing components need to be wrapped? +11. What selectors need to be added/wrapped? +12. What functions need to be overridden in afterLoad? + +### Authentication & Security +13. Are there new authentication types? +14. Do security schemes have new fields? +15. Are there new security requirements or flows? + +### Testing Strategy +16. Where are the official example specs? +17. What edge cases are mentioned in the spec? +18. What are the validation rules? + +### During Each Component +19. What is the exact field path in the spec? +20. What is the exact data type? +21. Is this field required or optional? +22. What are the constraints (min/max, enum, format)? +23. What are the examples in the spec? +24. How should this render visually? + +--- + +**Remember:** +1. **Always check https://spec.openapis.org/ first** +2. **Use WebFetch to analyze spec sections before coding** +3. **Follow the patterns established by OAS 3.1 implementation** +4. **Verify each component against the specification** +5. **Test with examples from the official spec** +6. **Document the spec reference in code comments** +7. **When in doubt, check the spec again!** diff --git a/src/main/webapp/swagger/.commitlintrc.json b/src/main/webapp/swagger/.commitlintrc.json new file mode 100644 index 00000000..a55865b3 --- /dev/null +++ b/src/main/webapp/swagger/.commitlintrc.json @@ -0,0 +1,25 @@ +{ + "extends": [ + "@commitlint/config-conventional" + ], + "rules": { + "header-max-length": [ + 2, + "always", + 69 + ], + "scope-case": [ + 2, + "always", + [ + "camel-case", + "kebab-case", + "upper-case" + ] + ], + "subject-case": [ + 0, + "always" + ] + } +} diff --git a/src/main/webapp/swagger/.dockerignore b/src/main/webapp/swagger/.dockerignore new file mode 100644 index 00000000..47c624e5 --- /dev/null +++ b/src/main/webapp/swagger/.dockerignore @@ -0,0 +1,8 @@ +/.git +/.github +/dev-helpers +/docs +/src +/swagger-ui-dist-package +/test +/node_modules \ No newline at end of file diff --git a/src/main/webapp/swagger/.editorconfig b/src/main/webapp/swagger/.editorconfig new file mode 100644 index 00000000..2d959463 --- /dev/null +++ b/src/main/webapp/swagger/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true +[*.md] +trim_trailing_whitespace = false diff --git a/src/main/webapp/swagger/.eslintignore b/src/main/webapp/swagger/.eslintignore new file mode 100644 index 00000000..5e20fb04 --- /dev/null +++ b/src/main/webapp/swagger/.eslintignore @@ -0,0 +1,3 @@ +dist/ +node_modules/ +test/e2e-selenium/ diff --git a/src/main/webapp/swagger/.eslintrc.js b/src/main/webapp/swagger/.eslintrc.js new file mode 100644 index 00000000..87d561e1 --- /dev/null +++ b/src/main/webapp/swagger/.eslintrc.js @@ -0,0 +1,78 @@ +/** + * @prettier + */ +const path = require("node:path") + +module.exports = { + parser: "@babel/eslint-parser", + env: { + browser: true, + node: true, + es6: true, + jest: true, + "jest/globals": true, + }, + parserOptions: { + ecmaFeatures: { jsx: true }, + babelOptions: { configFile: path.join(__dirname, "babel.config.js") }, + }, + extends: [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:prettier/recommended", + ], + plugins: ["react", "import", "jest", "prettier"], + settings: { + react: { + pragma: "React", + version: "15.0", + }, + }, + rules: { + semi: [2, "never"], + strict: 0, + quotes: [ + 2, + "double", + { + avoidEscape: true, + allowTemplateLiterals: true, + }, + ], + "no-unused-vars": 2, + "no-multi-spaces": 1, + camelcase: [ + "error", + { + allow: [ + "^UNSAFE_", + "^requestSnippetGenerator_", + "^JsonSchema_", + "^curl_", + "^dom_", + "^api_", + "^client_", + "^grant_", + "^code_", + "^redirect_", + "^spec", + ], + }, + ], + "no-use-before-define": [2, "nofunc"], + "no-underscore-dangle": 0, + "no-unused-expressions": 1, + "comma-dangle": 0, + "no-console": [ + 2, + { + allow: ["warn", "error"], + }, + ], + "react/jsx-no-bind": 1, + "react/jsx-no-target-blank": 2, + "react/display-name": 0, + "import/no-extraneous-dependencies": 2, + "react/jsx-filename-extension": 2, + }, +} diff --git a/src/main/webapp/swagger/.gitattributes b/src/main/webapp/swagger/.gitattributes new file mode 100644 index 00000000..5e49d7fd --- /dev/null +++ b/src/main/webapp/swagger/.gitattributes @@ -0,0 +1,4 @@ +docker-run.sh text eol=lf +/dist/*.map export-ignore +/test export-ignore +/docs export-ignore \ No newline at end of file diff --git a/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Bug_report.md b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..48861bf3 --- /dev/null +++ b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,73 @@ +--- +name: Bug report +about: Report an issue you're experiencing + +--- + + + +### Q&A (please complete the following information) + - OS: [e.g. macOS] + - Browser: [e.g. chrome, safari] + - Version: [e.g. 22] + - Method of installation: [e.g. npm, dist assets] + - Swagger-UI version: [e.g. 3.10.0] + - Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0] + +### Content & configuration + + +Example Swagger/OpenAPI definition: +```yaml +# your YAML here +``` + +Swagger-UI configuration options: +```js +SwaggerUI({ + // your config options here +}) +``` + +``` +?yourQueryStringConfig +``` + +### Describe the bug you're encountering + + +### To reproduce... + +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +### Expected behavior + + +### Screenshots + + +### Additional context or thoughts + diff --git a/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Feature_request.md b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000..5b18f43f --- /dev/null +++ b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,42 @@ +--- +name: Feature request +about: Suggest a new feature or enhancement for this project + +--- + + ### Content & configuration + +Swagger/OpenAPI definition: + ```yaml + # your YAML here + ``` + + Swagger-UI configuration options: + ```js + SwaggerUI({ + // your config options here + }) + ``` + + ``` + ?yourQueryStringConfig + ``` + + +### Is your feature request related to a problem? + + +### Describe the solution you'd like + + +### Describe alternatives you've considered + + +### Additional context + diff --git a/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Support.md b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Support.md new file mode 100644 index 00000000..92eb5e90 --- /dev/null +++ b/src/main/webapp/swagger/.github/ISSUE_TEMPLATE/Support.md @@ -0,0 +1,46 @@ +--- +name: Support +about: Ask a question or request help with your implementation. + +--- + + + +### Q&A (please complete the following information) + - OS: [e.g. macOS] + - Browser: [e.g. chrome, safari] + - Version: [e.g. 22] + - Method of installation: [e.g. npm, dist assets] + - Swagger-UI version: [e.g. 3.10.0] + - Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0] + +### Content & configuration + + +Swagger/OpenAPI definition: +```yaml +# your YAML here +``` + +Swagger-UI configuration options: +```js +SwaggerUI({ + // your config options here +}) +``` + +``` +?yourQueryStringConfig +``` + +### Screenshots + + +### How can we help? + diff --git a/src/main/webapp/swagger/.github/dependabot.yaml b/src/main/webapp/swagger/.github/dependabot.yaml new file mode 100644 index 00000000..6475663f --- /dev/null +++ b/src/main/webapp/swagger/.github/dependabot.yaml @@ -0,0 +1,35 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "23:00" + commit-message: + prefix: "chore" + include: "scope" + open-pull-requests-limit: 3 + ignore: + # node-fetch must be synced manually + - dependency-name: "node-fetch" + + - package-ecosystem: "docker" + # Look for a `Dockerfile` in the `root` directory + directory: "/" + # Check for updates once a week + schedule: + interval: "weekly" + time: "23:00" + + - package-ecosystem: "github-actions" + target-branch: "master" + directory: "/" + schedule: + interval: "daily" + time: "23:00" + commit-message: + prefix: "chore" + include: "scope" + open-pull-requests-limit: 3 + + diff --git a/src/main/webapp/swagger/.github/lock.yml b/src/main/webapp/swagger/.github/lock.yml new file mode 100644 index 00000000..e0b8c11a --- /dev/null +++ b/src/main/webapp/swagger/.github/lock.yml @@ -0,0 +1,15 @@ +daysUntilLock: 365 +skipCreatedBefore: 2017-03-29 # initial release of Swagger UI 3.0.0 +exemptLabels: [] +lockLabel: "locked-by: lock-bot" +setLockReason: false +only: issues +lockComment: false +# lockComment: | +# Locking due to inactivity. + +# This is done to avoid resurrecting old issues and bumping long threads with new, possibly unrelated content. + +# If you think you're experiencing something similar to what you've found here: please [open a new issue](https://github.com/swagger-api/swagger-ui/issues/new/choose), follow the template, and reference this issue in your report. + +# Thanks! diff --git a/src/main/webapp/swagger/.github/pull_request_template.md b/src/main/webapp/swagger/.github/pull_request_template.md new file mode 100644 index 00000000..64e9cf6f --- /dev/null +++ b/src/main/webapp/swagger/.github/pull_request_template.md @@ -0,0 +1,55 @@ + + +### Description + + + + +### Motivation and Context + + + + + + + +### How Has This Been Tested? + + + + + + +### Screenshots (if appropriate): + + + +## Checklist + + + +### My PR contains... + +- [ ] No code changes (`src/` is unmodified: changes to documentation, CI, metadata, etc.) +- [ ] Dependency changes (any modification to dependencies in `package.json`) +- [ ] Bug fixes (non-breaking change which fixes an issue) +- [ ] Improvements (misc. changes to existing features) +- [ ] Features (non-breaking change which adds functionality) + +### My changes... +- [ ] are breaking changes to a public API (config options, System API, major UI change, etc). +- [ ] are breaking changes to a private API (Redux, component props, utility functions, etc.). +- [ ] are breaking changes to a developer API (npm script behavior changes, new dev system dependencies, etc). +- [ ] are not breaking changes. + +### Documentation +- [ ] My changes do not require a change to the project documentation. +- [ ] My changes require a change to the project documentation. +- [ ] If yes to above: I have updated the documentation accordingly. + +### Automated tests +- [ ] My changes can not or do not need to be tested. +- [ ] My changes can and should be tested by unit and/or integration tests. +- [ ] If yes to above: I have added tests to cover my changes. +- [ ] If yes to above: I have taken care to cover edge cases in my tests. +- [ ] All new and existing tests passed. diff --git a/src/main/webapp/swagger/.github/workflows/codeql.yml b/src/main/webapp/swagger/.github/workflows/codeql.yml new file mode 100644 index 00000000..f8ba9eff --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/codeql.yml @@ -0,0 +1,63 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '16 04 * * 2' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + config: | + paths-ignore: + - 'dist/' + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}" diff --git a/src/main/webapp/swagger/.github/workflows/dependabot-merge.yml b/src/main/webapp/swagger/.github/workflows/dependabot-merge.yml new file mode 100644 index 00000000..9495d428 --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/dependabot-merge.yml @@ -0,0 +1,40 @@ +name: Merge me! + +on: + pull_request_target: + branches: [ master, next ] + +permissions: + contents: read + +jobs: + merge-me: + name: Merge me! + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + # This first step will fail if there's no metadata and so the approval + # will not occur. + - name: Dependabot metadata + id: dependabot-metadata + uses: dependabot/fetch-metadata@v3.0.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + # Here the PR gets approved. + - name: Approve a PR + if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }} + run: gh pr review --approve "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }} + # Finally, tell dependabot to merge the PR if all checks are successful + - name: Instruct dependabot to squash & merge + if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }} + uses: mshick/add-pr-comment@v3 + with: + repo-token: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }} + allow-repeats: true + message: | + @dependabot squash and merge + env: + GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }} diff --git a/src/main/webapp/swagger/.github/workflows/docker-build-push-unstable.yml b/src/main/webapp/swagger/.github/workflows/docker-build-push-unstable.yml new file mode 100644 index 00000000..2acfe76a --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/docker-build-push-unstable.yml @@ -0,0 +1,52 @@ +name: Build & Push SwaggerUI unstable Docker image + +on: + workflow_run: + workflows: ["Node.js CI"] + types: + - completed + branches: [master] + +jobs: + + build-push-unstable: + if: github.event.workflow_run.conclusion == 'success' + name: Build & Push SwaggerUI unstable Docker image + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Build SwaggerUI + run: npm run build + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to DockerHub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_SB_USERNAME }} + password: ${{ secrets.DOCKERHUB_SB_PASSWORD }} + + - name: Build docker image and push + uses: docker/build-push-action@v7 + with: + context: . + push: true + platforms: linux/amd64,linux/arm/v6,linux/arm64,linux/386,linux/ppc64le + provenance: false + tags: swaggerapi/swagger-ui:unstable diff --git a/src/main/webapp/swagger/.github/workflows/docker-build-push.yml b/src/main/webapp/swagger/.github/workflows/docker-build-push.yml new file mode 100644 index 00000000..c6460b53 --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/docker-build-push.yml @@ -0,0 +1,77 @@ +name: Build & Push SwaggerUI Docker image + +on: + workflow_run: + workflows: ["Release SwaggerUI"] + types: + - completed + branches: [master] + +jobs: + + build-push: + if: github.event.workflow_run.conclusion == 'success' + name: Build & Push SwaggerUI Docker image + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Build SwaggerUI + run: npm run build + + - name: Determine released version + uses: actions/github-script@v9 + with: + script: | + const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "released-version" + })[0]; + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + const fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/released-version.zip', Buffer.from(download.data)); + - run: | + unzip released-version.zip + RELEASED_VERSION=$(cat released-version.txt) + echo "RELEASED_VERSION=$RELEASED_VERSION" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to DockerHub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_SB_USERNAME }} + password: ${{ secrets.DOCKERHUB_SB_PASSWORD }} + + - name: Build docker image and push + uses: docker/build-push-action@v7 + with: + context: . + push: true + platforms: linux/amd64,linux/arm/v6,linux/arm64,linux/386,linux/ppc64le + provenance: false + tags: swaggerapi/swagger-ui:latest,swaggerapi/swagger-ui:v${{ env.RELEASED_VERSION }} diff --git a/src/main/webapp/swagger/.github/workflows/docker-image-check.yml b/src/main/webapp/swagger/.github/workflows/docker-image-check.yml new file mode 100644 index 00000000..dd119606 --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/docker-image-check.yml @@ -0,0 +1,23 @@ +name: Security scan for docker image + +on: + workflow_dispatch: + schedule: + - cron: '30 4 * * *' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: 'docker.swagger.io/swaggerapi/swagger-ui:unstable' + format: 'table' + exit-code: '1' + ignore-unfixed: true + vuln-type: 'os,library' + severity: 'CRITICAL,HIGH' diff --git a/src/main/webapp/swagger/.github/workflows/nodejs.yml b/src/main/webapp/swagger/.github/workflows/nodejs.yml new file mode 100644 index 00000000..0fba4b0c --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/nodejs.yml @@ -0,0 +1,86 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [ master, next ] + pull_request: + branches: [ master, next ] + +env: + CYPRESS_CACHE_FOLDER: cypress/cache + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + + - name: Cache Node Modules and Cypress binary + uses: actions/cache@v5 + id: cache-primes + with: + path: | + node_modules + ${{ env.CYPRESS_CACHE_FOLDER }} + key: ${{ runner.os }}-node-and-cypress-${{ hashFiles('package-lock.json') }} + + - name: Install dependencies + if: steps.cache-primes.outputs.cache-hit != 'true' + run: npm ci + + - name: Lint code for errors only + run: npm run lint-errors + + - name: Run all tests + run: npm run test:unit + env: + CI: true + + - name: Build SwaggerUI + run: npm run build + + - name: Test build artifacts + run: npm run test:artifact + + e2e-tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + containers: ['+(a11y|security|bugs)/**/*cy.js', 'features/**/+(o|d)*.cy.js', 'features/**/m*.cy.js', 'features/**/!(o|d|m)*.cy.js'] + + steps: + - uses: actions/checkout@v6 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + + - name: Cache Node Modules and Cypress binary + uses: actions/cache@v5 + id: cache-primes + with: + path: | + node_modules + ${{ env.CYPRESS_CACHE_FOLDER }} + key: ${{ runner.os }}-node-and-cypress-${{ hashFiles('package-lock.json') }} + + - name: Install dependencies + if: steps.cache-primes.outputs.cache-hit != 'true' + run: npm ci + + - name: Cypress Test + run: npx start-server-and-test cy:start http://localhost:3204 'npm run cy:run -- --spec "test/e2e-cypress/e2e/${{ matrix.containers }}"' diff --git a/src/main/webapp/swagger/.github/workflows/release-swagger-ui-dist.yml b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-dist.yml new file mode 100644 index 00000000..f738b84e --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-dist.yml @@ -0,0 +1,61 @@ +name: Release SwaggerUI Dist + +on: + workflow_run: + workflows: ["Release SwaggerUI"] + types: + - completed + branches: [ master ] + +jobs: + release-swagger-ui-dist: + if: github.event.workflow_run.conclusion == 'success' + name: Release swagger-ui-dist npm package + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + ref: master + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Download build artifact + uses: actions/github-script@v9 + with: + script: | + const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "dist" + })[0]; + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + const fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/dist.zip', Buffer.from(download.data)); + - run: | + unzip -o dist.zip -d dist + + - name: Publish to npmjs.com + run: ./deploy.sh + working-directory: ./swagger-ui-dist-package + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + PUBLISH_DIST: true diff --git a/src/main/webapp/swagger/.github/workflows/release-swagger-ui-packagist.yml b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-packagist.yml new file mode 100644 index 00000000..05d51750 --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-packagist.yml @@ -0,0 +1,21 @@ +name: Release SwaggerUI to Packagist + +on: + workflow_run: + workflows: ["Release SwaggerUI"] + types: + - completed + branches: [ master ] + +jobs: + release-swagger-ui-packagist: + if: github.event.workflow_run.conclusion == 'success' + name: Release swagger-ui to packagist + runs-on: ubuntu-latest + steps: + - name: Update SwaggerUI packagist package + run: | + curl --fail -X POST \ + -H "Content-Type: application/json" \ + "https://packagist.org/api/update-package?username=${{ secrets.PACKAGIST_USER }}&apiToken=${{ secrets.PACKAGIST_API_TOKEN }}" \ + -d "{\"repository\":{\"url\":\"https://packagist.org/packages/swagger-api/swagger-ui\"}}" diff --git a/src/main/webapp/swagger/.github/workflows/release-swagger-ui-react.yml b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-react.yml new file mode 100644 index 00000000..f37cf3ba --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/release-swagger-ui-react.yml @@ -0,0 +1,61 @@ +name: Release SwaggerUI React + +on: + workflow_run: + workflows: ["Release SwaggerUI"] + types: + - completed + branches: [ master ] + +jobs: + release-swagger-ui-react: + if: github.event.workflow_run.conclusion == 'success' + name: Release swagger-ui-react npm package + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + ref: master + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Download build artifact + uses: actions/github-script@v9 + with: + script: | + const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "dist" + })[0]; + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + const fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/dist.zip', Buffer.from(download.data)); + - run: | + unzip -o dist.zip -d dist + + - name: Publish to npmjs.com + run: ./run.sh + working-directory: ./flavors/swagger-ui-react/release + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + PUBLISH_FLAVOR_REACT: true diff --git a/src/main/webapp/swagger/.github/workflows/release-swagger-ui.yml b/src/main/webapp/swagger/.github/workflows/release-swagger-ui.yml new file mode 100644 index 00000000..2c53028d --- /dev/null +++ b/src/main/webapp/swagger/.github/workflows/release-swagger-ui.yml @@ -0,0 +1,95 @@ +name: Release SwaggerUI +on: + workflow_dispatch: + branches: + - master + +jobs: + release: + name: Release swagger-ui npm package + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + ref: master + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + cache: npm + cache-dependency-path: package-lock.json + + - name: Determine the next release version + uses: cycjimmy/semantic-release-action@v6 + with: + dry_run: true + extra_plugins: | + @semantic-release/git + @semantic-release/exec + env: + GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Nothing to release + if: ${{ env.NEXT_RELEASE_VERSION == '' }} + uses: actions/github-script@v9 + with: + script: | + core.setFailed('Nothing to release') + + - name: Install dependencies + run: npm ci + + - name: Prepare for the Release + env: + REACT_APP_VERSION: ${{ env.NEXT_RELEASE_VERSION }} + run: | + npm run test + npm run build + + - name: Semantic Release + id: semantic + uses: cycjimmy/semantic-release-action@v6 + with: + dry_run: false + extra_plugins: | + @semantic-release/git + env: + GITHUB_TOKEN: ${{ secrets.SWAGGER_BOT_GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Release failed + if: steps.semantic.outputs.new_release_published == 'false' + uses: actions/github-script@v9 + with: + script: | + core.setFailed('Release failed') + + - name: Release published + run: | + echo ${{ steps.semantic.outputs.new_release_version }} + echo ${{ steps.semantic.outputs.new_release_major_version }} + echo ${{ steps.semantic.outputs.new_release_minor_version }} + echo ${{ steps.semantic.outputs.new_release_patch_version }} + + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: dist + path: ./dist + + + - name: Prepare released version for uploading + shell: bash + run: | + echo ${{ steps.semantic.outputs.new_release_version }} > released-version.txt + - name: Upload released version + uses: actions/upload-artifact@v7 + with: + name: released-version + path: ./released-version.txt + retention-days: 1 diff --git a/src/main/webapp/swagger/.gitignore b/src/main/webapp/swagger/.gitignore new file mode 100644 index 00000000..e9578575 --- /dev/null +++ b/src/main/webapp/swagger/.gitignore @@ -0,0 +1,29 @@ +node_modules +.idea +.vscode +.deps_check +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local +.nyc_output +npm-debug.log* +.eslintcache +*.iml +selenium-debug.log +chromedriver.log +test/e2e/db.json +docs/_book +dev-helpers/examples + +# dist +flavors/**/dist/* +/lib +/es +dist/log* +/swagger-ui-*.tgz + +# Cypress +test/e2e-cypress/screenshots +test/e2e-cypress/videos diff --git a/src/main/webapp/swagger/.husky/commit-msg b/src/main/webapp/swagger/.husky/commit-msg new file mode 100755 index 00000000..951570f7 --- /dev/null +++ b/src/main/webapp/swagger/.husky/commit-msg @@ -0,0 +1 @@ +npx commitlint -e diff --git a/src/main/webapp/swagger/.husky/pre-commit b/src/main/webapp/swagger/.husky/pre-commit new file mode 100755 index 00000000..2312dc58 --- /dev/null +++ b/src/main/webapp/swagger/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/src/main/webapp/swagger/.lintstagedrc b/src/main/webapp/swagger/.lintstagedrc new file mode 100644 index 00000000..0b1dd617 --- /dev/null +++ b/src/main/webapp/swagger/.lintstagedrc @@ -0,0 +1,4 @@ +{ + "*.{js,jsx}": ["eslint --max-warnings 0"], + "*.scss": ["stylelint '**/*.scss'"] +} diff --git a/src/main/webapp/swagger/.npmignore b/src/main/webapp/swagger/.npmignore new file mode 100644 index 00000000..600fc159 --- /dev/null +++ b/src/main/webapp/swagger/.npmignore @@ -0,0 +1,16 @@ +* +*/ +!README.md +!NOTICE +!package.json +!dist/swagger-ui.js +!dist/swagger-ui.js.map +!dist/swagger-ui-bundle.js +!dist/swagger-ui-standalone-preset.js +!dist/swagger-ui-es-bundle.js +!dist/swagger-ui-es-bundle-core.js +!dist/swagger-ui-es-bundle-core.js.map +!dist/swagger-ui.css +!dist/swagger-ui.css.map +!dist/oauth2-redirect.html +!dist/oauth2-redirect.js \ No newline at end of file diff --git a/src/main/webapp/swagger/.npmrc b/src/main/webapp/swagger/.npmrc new file mode 100644 index 00000000..d508edc4 --- /dev/null +++ b/src/main/webapp/swagger/.npmrc @@ -0,0 +1 @@ +save-prefix="=" diff --git a/src/main/webapp/swagger/.nvmrc b/src/main/webapp/swagger/.nvmrc new file mode 100644 index 00000000..d845d9d8 --- /dev/null +++ b/src/main/webapp/swagger/.nvmrc @@ -0,0 +1 @@ +24.14.0 diff --git a/src/main/webapp/swagger/.prettierrc.yaml b/src/main/webapp/swagger/.prettierrc.yaml new file mode 100644 index 00000000..2e34d757 --- /dev/null +++ b/src/main/webapp/swagger/.prettierrc.yaml @@ -0,0 +1,5 @@ +semi: false +trailingComma: es5 +endOfLine: lf +requirePragma: true +insertPragma: true diff --git a/src/main/webapp/swagger/.releaserc b/src/main/webapp/swagger/.releaserc new file mode 100644 index 00000000..d90e9626 --- /dev/null +++ b/src/main/webapp/swagger/.releaserc @@ -0,0 +1,26 @@ +{ + "branches": [ + {"name": "master"} + ], + "tagFormat": "v${version}", + "plugins": [ + "@semantic-release/commit-analyzer", + [ + "@semantic-release/exec", + { + "verifyReleaseCmd": "echo \"NEXT_RELEASE_VERSION=${nextRelease.version}\" >> $GITHUB_ENV" + } + ], + "@semantic-release/release-notes-generator", + "@semantic-release/npm", + "@semantic-release/github", + ["@semantic-release/git", { + "assets": [ + "dist/*.{js,html,css}", + "package.json", + "package-lock.json" + ], + "message": "chore(release): cut the ${nextRelease.version} release\n\n${nextRelease.notes}" + }] + ] +} diff --git a/src/main/webapp/swagger/CLAUDE.md b/src/main/webapp/swagger/CLAUDE.md new file mode 100644 index 00000000..5148b423 --- /dev/null +++ b/src/main/webapp/swagger/CLAUDE.md @@ -0,0 +1,1072 @@ +# CLAUDE.md - Swagger UI Codebase Guide + +> **Last Updated:** 2026-02-24 +> **Version:** 5.32.0 (in development) +> **Purpose:** Comprehensive guide for AI assistants working with the Swagger UI codebase + +--- + +## Table of Contents + +1. [Repository Overview](#repository-overview) +2. [Project Architecture](#project-architecture) +3. [Development Setup](#development-setup) +4. [Build System](#build-system) +5. [Testing Infrastructure](#testing-infrastructure) +6. [Code Style & Conventions](#code-style--conventions) +7. [Git Workflow](#git-workflow) +8. [Plugin Architecture](#plugin-architecture) +9. [Key Files & Directories](#key-files--directories) +10. [Common Workflows](#common-workflows) +11. [Important Guidelines](#important-guidelines) + +--- + +## Repository Overview + +### What is Swagger UI? + +Swagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents. + +### Multi-Package Monorepo Structure + +This repository publishes **three different npm packages**: + +1. **swagger-ui** (main package) + - Traditional npm module for single-page applications + - Entry: `dist/swagger-ui.js` + - ES Module: `dist/swagger-ui-es-bundle-core.js` + - Includes dependency resolution via Webpack/Browserify + +2. **swagger-ui-dist** (distribution package) + - Dependency-free module for server-side projects + - Published separately via GitHub workflow + - Template location: `swagger-ui-dist-package/` + +3. **swagger-ui-react** (React component) + - React wrapper component + - Location: `flavors/swagger-ui-react/` + - Uses React hooks + - Released separately via GitHub workflow + +### OpenAPI Specification Compatibility + +- **Current Support:** OpenAPI 2.0, 3.0.x, 3.1.x +- **Latest Version:** v5.31.0 (supports up to OpenAPI 3.1.2) + +### License + +Apache 2.0 - See LICENSE and NOTICE files for details. + +--- + +## Project Architecture + +### Technology Stack + +**Core Framework:** +- React 18 (>=16.8.0 <20) - UI components +- Redux 5.0.1 - State management +- Redux Immutable 4.0.0 - Immutable state +- Immutable.js 3.x - Immutable data structures +- React Redux 9.2.0 - React-Redux bindings + +**API & Schema Processing:** +- swagger-client 3.36.0 - OpenAPI client +- js-yaml 4.1.1 - YAML parsing +- remarkable 2.0.1 - Markdown rendering + +**Security:** +- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention) +- serialize-error 8.1.0 - Error serialization + +**Build Tools:** +- Webpack 5.97.1 - Module bundling +- Babel 7.26.x - JavaScript transpilation +- sass-embedded 1.86.0 - SCSS compilation +- PostCSS - CSS processing + +**Testing:** +- Jest 29.7.0 - Unit testing +- Cypress 14.2.0 - E2E testing +- Enzyme 3.11.0 - React component testing + +**Development:** +- ESLint 8.57.0 - JavaScript linting +- Prettier 3.5.3 - Code formatting +- Stylelint 16.19.1 - CSS linting +- Husky 9.1.7 - Git hooks +- lint-staged 15.5.0 - Pre-commit linting + +### Plugin-Based Architecture + +Swagger UI uses a **sophisticated plugin system** powered by Redux. The core system (`src/core/system.js`) manages: + +- Plugin registration and lifecycle +- Redux store creation and middleware +- State plugin combination +- Action/selector binding +- Configuration management + +**26 Core Plugins** (in `src/core/plugins/`): +- `auth` - Authentication handling +- `configs` - Configuration management +- `deep-linking` - URL-based navigation +- `download-url` - Spec downloading +- `err` - Error handling and transformation +- `filter` - API filtering +- `icons` - Icon components +- `json-schema-2020-12` - JSON Schema 2020-12 support +- `json-schema-2020-12-samples` - Sample generation +- `json-schema-5` - JSON Schema Draft 5 support +- `json-schema-5-samples` - Sample generation for Draft 5 +- `layout` - Layout system +- `logs` - Logging +- `oas3` - OpenAPI 3.0.x support +- `oas31` - OpenAPI 3.1.x support +- `oas32` - OpenAPI 3.2.x support +- `on-complete` - Completion callbacks +- `request-snippets` - Code snippet generation +- `safe-render` - Safe component rendering +- `spec` - Specification handling +- `swagger-client` - API client integration +- `syntax-highlighting` - Code highlighting +- `util` - Utilities +- `versions` - Version detection +- `view` - View rendering +- `view-legacy` - Legacy view support + +--- + +## Development Setup + +### Prerequisites + +- **Node.js:** >=24.14.0 (Node 24.x recommended, as defined in `.nvmrc`) +- **npm:** >=11.9.0 +- **Git:** Any version +- **JDK 7+:** Required for Nightwatch.js integration tests + +### Installation Steps + +```bash +# Clone the repository +git clone https://github.com/swagger-api/swagger-ui.git +cd swagger-ui + +# Install dependencies +npm install + +# Initialize Husky (optional, for git hooks) +npx husky init + +# Start development server +npm run dev + +# Open http://localhost:3200/ +``` + +### Development Server + +The `npm run dev` command starts a hot-reloading Webpack dev server on **port 3200**. + +### Using Local API Definitions + +Edit `dev-helpers/dev-helper-initializer.js` to change the spec URL: + +```javascript +// Replace +url: "https://petstore.swagger.io/v2/swagger.json", + +// With +url: "./examples/your-local-api-definition.yaml", +``` + +**Important:** Local files must be in the `dev-helpers/` directory or subdirectory. Use `dev-helpers/examples/` (already in `.gitignore`). + +--- + +## Build System + +### Babel Environments + +Three Babel environments configured in `babel.config.js`: + +1. **development/production** - Browser builds with `modules: "auto"` +2. **commonjs** - CommonJS modules with `modules: "commonjs"` for Node.js +3. **esm** - ES modules with `modules: false` for modern bundlers + +### Babel Aliases + +```javascript +{ + root: ".", + core: "./src/core" +} +``` + +### Browserslist Environments + +Defined in `.browserslistrc`: + +- `[browser-production]` - Production browser targets +- `[browser-development]` - Latest Chrome, Firefox, Safari +- `[isomorphic-production]` - Browser + Node targets +- `[node-production]` - Maintained Node versions +- `[node-development]` - Node 24 + +### Build Commands + +```bash +# Full build (stylesheets + all bundles) +npm run build + +# Individual builds +npm run build:core # Core bundle (browser) +npm run build:bundle # Isomorphic bundle +npm run build:standalone # Standalone preset +npm run build:es:bundle # ES module bundle +npm run build:es:bundle:core # ES module core +npm run build-stylesheets # CSS only + +# Clean build artifacts +npm run clean +``` + +### Build Output (dist/) + +- `swagger-ui.js` - Core bundle (CommonJS) +- `swagger-ui.css` - Compiled styles +- `swagger-ui-bundle.js` - Isomorphic bundle +- `swagger-ui-standalone-preset.js` - Standalone preset +- `swagger-ui-es-bundle.js` - ES module bundle +- `swagger-ui-es-bundle-core.js` - ES module core +- `oauth2-redirect.html` - OAuth2 redirect page + +### Webpack Configurations + +Located in `webpack/` directory: + +- `_config-builder.js` - Base configuration +- `core.js` - Core build +- `bundle.js` - Bundle build +- `standalone.js` - Standalone build +- `es-bundle.js` - ES bundle +- `es-bundle-core.js` - ES core bundle +- `stylesheets.js` - CSS build +- `dev.js` - Development server +- `dev-e2e.js` - E2E testing server + +--- + +## Testing Infrastructure + +### Unit Tests (Jest) + +**Configuration:** `config/jest/jest.unit.config.js` + +**Environment:** jsdom (simulates browser environment) + +**Location:** `test/unit/` + +**Command:** +```bash +npm run test:unit +``` + +**Key Features:** +- 37 unit test files +- Tests for core plugins, components, system +- XSS security tests +- Silent mode enabled by default (set to `false` for console output) +- Module name mapper for SVG and standalone imports +- Transform ignore patterns for node_modules exceptions + +**Setup Files:** +- `test/unit/jest-shim.js` - Polyfills and shims +- `test/unit/setup.js` - Test environment setup + +### E2E Tests (Cypress) + +**Configuration:** `cypress.config.js` + +**Location:** `test/e2e-cypress/` + +**Base URL:** http://localhost:3230/ + +**Commands:** +```bash +# Run all E2E tests +npm run cy:ci + +# Interactive Cypress runner +npm run cy:dev + +# Headless run +npm run cy:run + +# Start servers and run tests +npm run cy:start # Starts webpack + mock API +``` + +**Structure:** +- `test/e2e-cypress/e2e/` - Test specs (99 test files) +- `test/e2e-cypress/static/` - Test fixtures and documents +- `test/e2e-cypress/support/` - Test helpers and commands + +**Test Categories:** +- `a11y/**/*cy.js` - Accessibility tests +- `security/**/*cy.js` - Security tests +- `bugs/**/*cy.js` - Bug regression tests +- `features/**/*cy.js` - Feature tests + +**Mock API Server:** +```bash +npm run cy:mock-api # JSON Server on port 3204 +``` + +### Artifact Tests + +**Configuration:** `config/jest/jest.artifact.config.js` + +**Purpose:** Verify build artifacts export correctly + +**Command:** +```bash +npm run test:artifact +``` + +### Complete Test Suite + +```bash +npm test # Runs: lint-errors + test:unit + cy:ci +``` + +### CI/CD Testing + +**GitHub Actions Workflow:** `.github/workflows/nodejs.yml` + +**Two Jobs:** +1. **build** - Lint, unit tests, build, artifact tests +2. **e2e-tests** - Cypress tests (matrix strategy with 3 containers) + +**Branches:** `master`, `next` + +--- + +## Code Style & Conventions + +### ESLint Configuration + +**File:** `.eslintrc.js` + +**Parser:** `@babel/eslint-parser` + +**Key Rules:** +- `semi: [2, "never"]` - **No semicolons** +- `quotes: [2, "double"]` - **Double quotes** (allow template literals) +- `no-unused-vars: 2` - Error on unused variables +- `camelcase: ["error"]` - Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.) +- `no-console: [2, {allow: ["warn", "error"]}]` - Only `console.warn` and `console.error` allowed +- `react/jsx-no-bind: 1` - Warning for JSX bind +- `react/jsx-filename-extension: 2` - JSX only in `.jsx` files +- `import/no-extraneous-dependencies: 2` - Error on extraneous dependencies + +**Extends:** +- `eslint:recommended` +- `plugin:react/recommended` +- `plugin:prettier/recommended` + +### Prettier Configuration + +**File:** `.prettierrc.yaml` + +**Settings:** +```yaml +semi: false # No semicolons +trailingComma: es5 # ES5 trailing commas +endOfLine: lf # Unix line endings +requirePragma: true # Require @prettier pragma +insertPragma: true # Insert @prettier pragma +``` + +**IMPORTANT:** Prettier requires `@prettier` pragma comment at the top of files: +```javascript +/** + * @prettier + */ +``` + +### Stylelint Configuration + +**File:** `stylelint.config.js` + +**Custom Syntax:** `postcss-scss` + +**Rules:** +- Uses `stylelint-prettier` plugin +- Prettier integration without pragma requirement + +### Pre-commit Hooks + +**Husky:** `.husky/pre-commit` runs `npx lint-staged` + +**Lint-staged Configuration:** `.lintstagedrc` +```json +{ + "*.{js,jsx}": ["eslint --max-warnings 0"], + "*.scss": ["stylelint '**/*.scss'"] +} +``` + +**Critical:** All staged JS/JSX/SCSS files are linted with **zero warnings tolerance**. + +### File Structure Conventions + +**Components:** +- Location: `src/core/components/` +- Extension: `.jsx` (React components) +- Format: PascalCase for component names + +**Styles:** +- Location: `src/style/` +- Extension: `.scss` +- Format: SCSS with PostCSS processing +- Dark mode: `_dark-mode.scss` + +**Tests:** +- Unit: `test/unit/` (mirrors source structure) +- E2E: `test/e2e-cypress/e2e/` +- Naming: `*.test.js`, `*.spec.js`, `*.cy.js` (Cypress) + +--- + +## Git Workflow + +### Branch Strategy + +**Main Branches:** +- `master` - Production releases +- `next` - Next version development + +**Feature Branches:** +- Should branch from `master` or `next` +- Use descriptive names + +### Commit Conventions + +**Format:** Conventional Commits (enforced by commitlint) + +**Structure:** +``` +(): + + + +