Commit pour la declarations et lenregistrement de la donnéePremierCommit_GTF
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\",
|
||||
"Documents": [],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js||{14D17961-FE51-464D-9111-C4AF11D7D99A}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:GTF\\project\\backend\\config\\test-db.js||{14D17961-FE51-464D-9111-C4AF11D7D99A}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php||{3B902123-F8A7-4915-9F01-361F908088D0}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:GTF\\project\\backend\\db.php||{3B902123-F8A7-4915-9F01-361F908088D0}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "test-db.js",
|
||||
"DocumentMoniker": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js",
|
||||
"RelativeDocumentMoniker": "GTF\\project\\backend\\config\\test-db.js",
|
||||
"ToolTip": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js",
|
||||
"RelativeToolTip": "GTF\\project\\backend\\config\\test-db.js",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAABMAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001646|",
|
||||
"WhenOpened": "2025-09-15T08:03:52.452Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "db.php",
|
||||
"DocumentMoniker": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php",
|
||||
"RelativeDocumentMoniker": "GTF\\project\\backend\\db.php",
|
||||
"ToolTip": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php",
|
||||
"RelativeToolTip": "GTF\\project\\backend\\db.php",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.002338|",
|
||||
"WhenOpened": "2025-09-15T08:00:38.102Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"CurrentProjectSetting": null
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
"",
|
||||
"\\GTF",
|
||||
"\\GTF\\project",
|
||||
"\\GTF\\project\\backend",
|
||||
"\\GTF\\project\\backend\\config"
|
||||
],
|
||||
"SelectedNode": "\\GTF\\project\\backend\\config\\test-db.js",
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
BIN
.vs/slnx.sqlite
BIN
.vs/slnx.sqlite
Binary file not shown.
@@ -1,5 +1,7 @@
|
||||
DB_SERVER=Localhost
|
||||
DB_SERVER=BONEMINE
|
||||
DB_DATABASE=GTF
|
||||
DB_USER=ENSUP\oimer
|
||||
DB_PASSWORD=Wijdane123@
|
||||
DB_USER=gtf_app
|
||||
DB_PASSWORD=GTF2025!Secure
|
||||
DB_ENCRYPT=true
|
||||
DB_TRUST_SERVER_CERTIFICATE=true
|
||||
PORT=3001
|
||||
282
GTF/project/backend/config/server.js
Normal file
282
GTF/project/backend/config/server.js
Normal file
@@ -0,0 +1,282 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const sql = require('mssql');
|
||||
require('dotenv').config();
|
||||
|
||||
const app = express();
|
||||
const PORT = 3001;
|
||||
|
||||
// Configuration base de données
|
||||
const dbConfig = {
|
||||
server: process.env.DB_SERVER,
|
||||
database: process.env.DB_DATABASE,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
options: {
|
||||
encrypt: true,
|
||||
trustServerCertificate: true,
|
||||
enableArithAbort: true
|
||||
}
|
||||
};
|
||||
|
||||
// Middleware
|
||||
app.use(cors({
|
||||
origin: ['http://localhost:5173', 'http://localhost:3000', 'http://127.0.0.1:5173'],
|
||||
credentials: true
|
||||
}));
|
||||
app.use(express.json());
|
||||
|
||||
// Log de toutes les requêtes
|
||||
app.use((req, res, next) => {
|
||||
console.log(`${new Date().toISOString()} - ${req.method} ${req.path} depuis ${req.get('origin') || 'inconnu'}`);
|
||||
next();
|
||||
});
|
||||
|
||||
// Variable pour stocker la connexion
|
||||
let pool = null;
|
||||
|
||||
// Fonction pour se connecter à la base
|
||||
async function connectDatabase() {
|
||||
try {
|
||||
pool = await sql.connect(dbConfig);
|
||||
console.log('Base de données connectée');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Erreur de connexion :', error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Route de test
|
||||
app.get('/api/test', (req, res) => {
|
||||
res.json({
|
||||
message: 'Le serveur fonctionne !',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour tester la base de données
|
||||
app.get('/api/db-test', async (req, res) => {
|
||||
try {
|
||||
if (!pool) {
|
||||
return res.status(500).json({ error: 'Base non connectée' });
|
||||
}
|
||||
|
||||
const result = await pool.request().query('SELECT COUNT(*) as total FROM FormateurSqy');
|
||||
res.json({
|
||||
message: 'Base OK',
|
||||
formateurs: result.recordset[0].total
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour lister les formateurs
|
||||
app.get('/api/formateurs', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.request().query(`
|
||||
SELECT TOP 10
|
||||
NUMERO,
|
||||
NOM_ENS as nom,
|
||||
PRENOM_ENS as prenom,
|
||||
EMAIL1 as email
|
||||
FROM FormateurSqy
|
||||
WHERE EMAIL1 IS NOT NULL
|
||||
ORDER BY NOM_ENS
|
||||
`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.recordset
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour sauvegarder une déclaration
|
||||
app.post('/api/save_declaration', async (req, res) => {
|
||||
try {
|
||||
const { date, activityType, hours, description, user } = req.body;
|
||||
|
||||
console.log('Données reçues:', { date, activityType, hours, description, user });
|
||||
|
||||
// Validation simple
|
||||
if (!date || !activityType || !hours) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Données manquantes'
|
||||
});
|
||||
}
|
||||
|
||||
let formateurNumero;
|
||||
|
||||
if (user && user.email) {
|
||||
// Chercher le formateur par email
|
||||
const formateurResult = await pool.request()
|
||||
.input('email', sql.VarChar, user.email)
|
||||
.query('SELECT NUMERO FROM FormateurSqy WHERE EMAIL1 = @email');
|
||||
|
||||
if (formateurResult.recordset.length > 0) {
|
||||
// Formateur trouvé
|
||||
formateurNumero = formateurResult.recordset[0].NUMERO;
|
||||
console.log('Formateur trouvé par email:', formateurNumero);
|
||||
} else {
|
||||
// Créer un nouveau formateur
|
||||
const maxNumeroResult = await pool.request()
|
||||
.query('SELECT ISNULL(MAX(NUMERO), 0) + 1 as nextNumero FROM FormateurSqy');
|
||||
|
||||
const nextNumero = maxNumeroResult.recordset[0].nextNumero;
|
||||
|
||||
await pool.request()
|
||||
.input('numero', sql.Int, nextNumero)
|
||||
.input('nom', sql.VarChar, user.nom || 'Inconnu')
|
||||
.input('prenom', sql.VarChar, user.prenom || 'Inconnu')
|
||||
.input('email', sql.VarChar, user.email)
|
||||
.input('department', sql.VarChar, user.department || 'Non défini')
|
||||
.input('role', sql.VarChar, user.role || 'Employé')
|
||||
.query(`
|
||||
INSERT INTO FormateurSqy (
|
||||
NUMERO, NOM_ENS, PRENOM_ENS, EMAIL1, [Ecole - Pole], Contrat
|
||||
) VALUES (
|
||||
@numero, @nom, @prenom, @email, @department, @role
|
||||
)
|
||||
`);
|
||||
|
||||
formateurNumero = nextNumero;
|
||||
console.log('Nouveau formateur créé:', formateurNumero);
|
||||
}
|
||||
} else {
|
||||
// Fallback : utiliser un formateur par défaut
|
||||
formateurNumero = 999;
|
||||
console.log('Utilisation du formateur par défaut:', formateurNumero);
|
||||
}
|
||||
|
||||
// Récupérer l'ID du type de demande
|
||||
const typeResult = await pool.request()
|
||||
.input('activityType', sql.VarChar, activityType)
|
||||
.query('SELECT id FROM types_demandes WHERE libelle = @activityType');
|
||||
|
||||
if (typeResult.recordset.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: `Type d'activité invalide: ${activityType}`
|
||||
});
|
||||
}
|
||||
|
||||
const typeDemandeId = typeResult.recordset[0].id;
|
||||
|
||||
// Vérifier si une déclaration existe déjà pour cette date
|
||||
const existingResult = await pool.request()
|
||||
.input('formateurNumero', sql.Int, formateurNumero)
|
||||
.input('date', sql.Date, date)
|
||||
.query('SELECT id FROM declarations WHERE formateur_numero = @formateurNumero AND date = @date');
|
||||
|
||||
if (existingResult.recordset.length > 0) {
|
||||
// Mise à jour
|
||||
await pool.request()
|
||||
.input('utilisateurId', sql.Int, formateurNumero)
|
||||
.input('typeDemandeId', sql.Int, typeDemandeId)
|
||||
.input('hours', sql.Float, hours)
|
||||
.input('description', sql.NVarChar, description || null)
|
||||
.input('formateurNumero', sql.Int, formateurNumero)
|
||||
.input('date', sql.Date, date)
|
||||
.query(`
|
||||
UPDATE declarations
|
||||
SET utilisateur_id = @utilisateurId, type_demande_id = @typeDemandeId, duree = @hours, description = @description
|
||||
WHERE formateur_numero = @formateurNumero AND date = @date
|
||||
`);
|
||||
|
||||
console.log('Déclaration mise à jour');
|
||||
} else {
|
||||
// Création
|
||||
await pool.request()
|
||||
.input('utilisateurId', sql.Int, formateurNumero)
|
||||
.input('formateurNumero', sql.Int, formateurNumero)
|
||||
.input('typeDemandeId', sql.Int, typeDemandeId)
|
||||
.input('date', sql.Date, date)
|
||||
.input('hours', sql.Float, hours)
|
||||
.input('description', sql.NVarChar, description || null)
|
||||
.query(`
|
||||
INSERT INTO declarations (utilisateur_id, formateur_numero, type_demande_id, date, duree, description)
|
||||
VALUES (@utilisateurId, @formateurNumero, @typeDemandeId, @date, @hours, @description)
|
||||
`);
|
||||
|
||||
console.log('Nouvelle déclaration créée');
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Déclaration sauvegardée avec succès'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la sauvegarde:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Route pour récupérer les déclarations
|
||||
app.get('/api/get_declarations', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.request().query(`
|
||||
SELECT
|
||||
d.id,
|
||||
d.formateur_numero as utilisateur_id,
|
||||
td.id as type_demande_id,
|
||||
d.date,
|
||||
d.duree,
|
||||
d.description,
|
||||
d.formateur_numero,
|
||||
td.libelle as activityType
|
||||
FROM declarations d
|
||||
INNER JOIN types_demandes td ON d.type_demande_id = td.id
|
||||
ORDER BY d.date DESC
|
||||
`);
|
||||
|
||||
res.json(result.recordset);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Démarrage du serveur
|
||||
async function startServer() {
|
||||
const dbConnected = await connectDatabase();
|
||||
|
||||
if (!dbConnected) {
|
||||
console.log('Impossible de démarrer sans base de données');
|
||||
return;
|
||||
}
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Serveur démarré sur http://localhost:${PORT}`);
|
||||
console.log('Routes disponibles :');
|
||||
console.log('- GET /api/test');
|
||||
console.log('- GET /api/db-test');
|
||||
console.log('- GET /api/formateurs');
|
||||
console.log('- POST /api/save_declaration');
|
||||
console.log('- GET /api/get_declarations');
|
||||
});
|
||||
}
|
||||
|
||||
// Arrêt propre
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Arrêt du serveur...');
|
||||
if (pool) {
|
||||
await pool.close();
|
||||
}
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Démarrer
|
||||
startServer();
|
||||
@@ -1,36 +1,59 @@
|
||||
// Test avec authentification Windows
|
||||
// Test avec authentification SQL Server
|
||||
const sql = require('mssql');
|
||||
|
||||
const config = {
|
||||
server: '16.0.1000.6',
|
||||
server: 'BONEMINE',
|
||||
database: 'GTF',
|
||||
user: 'gtf_app',
|
||||
password: 'GTF2025!Secure',
|
||||
options: {
|
||||
encrypt: true,
|
||||
trustServerCertificate: true,
|
||||
trustedConnection: true, // Utilise votre compte Windows actuel
|
||||
enableArithAbort: true
|
||||
}
|
||||
};
|
||||
|
||||
async function testConnection() {
|
||||
try {
|
||||
console.log('🔄 Test avec authentification Windows...');
|
||||
console.log('Utilisateur Windows actuel:', process.env.USERNAME);
|
||||
console.log('Test avec authentification SQL Server...');
|
||||
console.log('Serveur:', config.server);
|
||||
console.log('Base:', config.database);
|
||||
console.log('Utilisateur:', config.user);
|
||||
|
||||
await sql.connect(config);
|
||||
console.log('✅ Connexion réussie avec Windows Auth !');
|
||||
console.log('Connexion réussie avec SQL Server Auth !');
|
||||
|
||||
const result = await sql.query('SELECT COUNT(*) as total FROM FormateurSqy');
|
||||
console.log('📊 Nombre de formateurs :', result.recordset[0].total);
|
||||
// Test des tables
|
||||
const result1 = await sql.query('SELECT COUNT(*) as total FROM FormateurSqy');
|
||||
console.log('Nombre de formateurs :', result1.recordset[0].total);
|
||||
|
||||
const result2 = await sql.query('SELECT COUNT(*) as total FROM declarations');
|
||||
console.log('📊 Nombre de déclarations :', result2.recordset[0].total);
|
||||
console.log('Nombre de déclarations :', result2.recordset[0].total);
|
||||
|
||||
console.log('🎉 Parfait ! Votre authentification Windows fonctionne.');
|
||||
const result3 = await sql.query('SELECT COUNT(*) as total FROM types_demandes');
|
||||
console.log('Nombre de types de demandes :', result3.recordset[0].total);
|
||||
|
||||
// Test d'insertion/lecture (pour vérifier les permissions)
|
||||
const testResult = await sql.query(`
|
||||
SELECT
|
||||
id,
|
||||
libelle
|
||||
FROM types_demandes
|
||||
`);
|
||||
console.log('Types de demandes disponibles :');
|
||||
testResult.recordset.forEach(t => {
|
||||
console.log(`- ${t.id}: ${t.libelle}`);
|
||||
});
|
||||
|
||||
console.log('Configuration SQL Server validée !');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur :', error.message);
|
||||
console.log('💡 Suggestion : Vérifiez que votre utilisateur Windows a accès à la base GTF');
|
||||
console.error('Erreur :', error.message);
|
||||
console.log('Code d\'erreur:', error.code);
|
||||
|
||||
if (error.code === 'ELOGIN') {
|
||||
console.log('Vérifiez que l\'utilisateur gtf_app a été créé dans SQL Server');
|
||||
}
|
||||
} finally {
|
||||
await sql.close();
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
// db.php
|
||||
$serverName = "BONEMINE";
|
||||
$connectionOptions = [
|
||||
"Database" => "GTF",
|
||||
"Uid" => "oimer",
|
||||
"PWD" => "Wijdane123@",
|
||||
"CharacterSet" => "UTF-8"
|
||||
];
|
||||
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
?>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
header("Content-Type: application/json");
|
||||
require_once "db.php";
|
||||
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
if (!$conn) {
|
||||
die(json_encode(["error" => sqlsrv_errors()]));
|
||||
}
|
||||
|
||||
$sql = "SELECT id, utilisateur_id, type_demande_id, CONVERT(varchar, date, 23) as date, duree, description, formateur_numero FROM declarations";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
|
||||
$data = [];
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
echo json_encode($data);
|
||||
22
GTF/project/backend/node_modules/.package-lock.json
generated
vendored
22
GTF/project/backend/node_modules/.package-lock.json
generated
vendored
@@ -523,6 +523,19 @@
|
||||
"node": ">=6.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
@@ -1196,6 +1209,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.4",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||
|
||||
33
GTF/project/backend/node_modules/cors/CONTRIBUTING.md
generated
vendored
Normal file
33
GTF/project/backend/node_modules/cors/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# contributing to `cors`
|
||||
|
||||
CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md).
|
||||
|
||||
## The CORS Spec
|
||||
|
||||
[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/)
|
||||
|
||||
## Pull Requests Welcome
|
||||
|
||||
* Include `'use strict';` in every javascript file.
|
||||
* 2 space indentation.
|
||||
* Please run the testing steps below before submitting.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## Interactive Testing Harness
|
||||
|
||||
[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com)
|
||||
|
||||
Related git repositories:
|
||||
|
||||
* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||
* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
58
GTF/project/backend/node_modules/cors/HISTORY.md
generated
vendored
Normal file
58
GTF/project/backend/node_modules/cors/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
2.8.5 / 2018-11-04
|
||||
==================
|
||||
|
||||
* Fix setting `maxAge` option to `0`
|
||||
|
||||
2.8.4 / 2017-07-12
|
||||
==================
|
||||
|
||||
* Work-around Safari bug in default pre-flight response
|
||||
|
||||
2.8.3 / 2017-03-29
|
||||
==================
|
||||
|
||||
* Fix error when options delegate missing `methods` option
|
||||
|
||||
2.8.2 / 2017-03-28
|
||||
==================
|
||||
|
||||
* Fix error when frozen options are passed
|
||||
* Send "Vary: Origin" when using regular expressions
|
||||
* Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders`
|
||||
|
||||
2.8.1 / 2016-09-08
|
||||
==================
|
||||
|
||||
This release only changed documentation.
|
||||
|
||||
2.8.0 / 2016-08-23
|
||||
==================
|
||||
|
||||
* Add `optionsSuccessStatus` option
|
||||
|
||||
2.7.2 / 2016-08-23
|
||||
==================
|
||||
|
||||
* Fix error when Node.js running in strict mode
|
||||
|
||||
2.7.1 / 2015-05-28
|
||||
==================
|
||||
|
||||
* Move module into expressjs organization
|
||||
|
||||
2.7.0 / 2015-05-28
|
||||
==================
|
||||
|
||||
* Allow array of matching condition as `origin` option
|
||||
* Allow regular expression as `origin` option
|
||||
|
||||
2.6.1 / 2015-05-28
|
||||
==================
|
||||
|
||||
* Update `license` in package.json
|
||||
|
||||
2.6.0 / 2015-04-27
|
||||
==================
|
||||
|
||||
* Add `preflightContinue` option
|
||||
* Fix "Vary: Origin" header added for "*"
|
||||
22
GTF/project/backend/node_modules/cors/LICENSE
generated
vendored
Normal file
22
GTF/project/backend/node_modules/cors/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2013 Troy Goode <troygoode@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
243
GTF/project/backend/node_modules/cors/README.md
generated
vendored
Normal file
243
GTF/project/backend/node_modules/cors/README.md
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
# cors
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options.
|
||||
|
||||
**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)**
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Usage](#usage)
|
||||
* [Simple Usage](#simple-usage-enable-all-cors-requests)
|
||||
* [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
|
||||
* [Configuring CORS](#configuring-cors)
|
||||
* [Configuring CORS Asynchronously](#configuring-cors-asynchronously)
|
||||
* [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
|
||||
* [Configuration Options](#configuration-options)
|
||||
* [Demo](#demo)
|
||||
* [License](#license)
|
||||
* [Author](#author)
|
||||
|
||||
## Installation
|
||||
|
||||
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||
|
||||
```sh
|
||||
$ npm install cors
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Simple Usage (Enable *All* CORS Requests)
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
app.use(cors())
|
||||
|
||||
app.get('/products/:id', function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for all origins!'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
### Enable CORS for a Single Route
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
app.get('/products/:id', cors(), function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for a Single Route'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
### Configuring CORS
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
var corsOptions = {
|
||||
origin: 'http://example.com',
|
||||
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
|
||||
}
|
||||
|
||||
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for only example.com.'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
### Configuring CORS w/ Dynamic Origin
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
var whitelist = ['http://example1.com', 'http://example2.com']
|
||||
var corsOptions = {
|
||||
origin: function (origin, callback) {
|
||||
if (whitelist.indexOf(origin) !== -1) {
|
||||
callback(null, true)
|
||||
} else {
|
||||
callback(new Error('Not allowed by CORS'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
If you do not want to block REST tools or server-to-server requests,
|
||||
add a `!origin` check in the origin function like so:
|
||||
|
||||
```javascript
|
||||
var corsOptions = {
|
||||
origin: function (origin, callback) {
|
||||
if (whitelist.indexOf(origin) !== -1 || !origin) {
|
||||
callback(null, true)
|
||||
} else {
|
||||
callback(new Error('Not allowed by CORS'))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Enabling CORS Pre-Flight
|
||||
|
||||
Certain CORS requests are considered 'complex' and require an initial
|
||||
`OPTIONS` request (called the "pre-flight request"). An example of a
|
||||
'complex' CORS request is one that uses an HTTP verb other than
|
||||
GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
|
||||
pre-flighting, you must add a new OPTIONS handler for the route you want
|
||||
to support:
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
|
||||
app.del('/products/:id', cors(), function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for all origins!'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
You can also enable pre-flight across-the-board like so:
|
||||
|
||||
```javascript
|
||||
app.options('*', cors()) // include before other routes
|
||||
```
|
||||
|
||||
### Configuring CORS Asynchronously
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var cors = require('cors')
|
||||
var app = express()
|
||||
|
||||
var whitelist = ['http://example1.com', 'http://example2.com']
|
||||
var corsOptionsDelegate = function (req, callback) {
|
||||
var corsOptions;
|
||||
if (whitelist.indexOf(req.header('Origin')) !== -1) {
|
||||
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
|
||||
} else {
|
||||
corsOptions = { origin: false } // disable CORS for this request
|
||||
}
|
||||
callback(null, corsOptions) // callback expects two parameters: error and options
|
||||
}
|
||||
|
||||
app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
|
||||
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
|
||||
})
|
||||
|
||||
app.listen(80, function () {
|
||||
console.log('CORS-enabled web server listening on port 80')
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
|
||||
- `Boolean` - set `origin` to `true` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
|
||||
- `String` - set `origin` to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed.
|
||||
- `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
|
||||
- `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
|
||||
- `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature `err [object], allow [bool]`) as the second.
|
||||
* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
|
||||
* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
|
||||
* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
|
||||
* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
|
||||
* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
|
||||
* `preflightContinue`: Pass the CORS preflight response to the next handler.
|
||||
* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
|
||||
|
||||
The default configuration is the equivalent of:
|
||||
|
||||
```json
|
||||
{
|
||||
"origin": "*",
|
||||
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||
"preflightContinue": false,
|
||||
"optionsSuccessStatus": 204
|
||||
}
|
||||
```
|
||||
|
||||
For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) article on HTML5 Rocks.
|
||||
|
||||
## Demo
|
||||
|
||||
A demo that illustrates CORS working (and not working) using jQuery is available here: [http://node-cors-client.herokuapp.com/](http://node-cors-client.herokuapp.com/)
|
||||
|
||||
Code for that demo can be found here:
|
||||
|
||||
* Client: [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||
* Server: [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
|
||||
## Author
|
||||
|
||||
[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
|
||||
|
||||
[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
|
||||
[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/cors.svg
|
||||
[downloads-url]: https://npmjs.org/package/cors
|
||||
[npm-image]: https://img.shields.io/npm/v/cors.svg
|
||||
[npm-url]: https://npmjs.org/package/cors
|
||||
[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg
|
||||
[travis-url]: https://travis-ci.org/expressjs/cors
|
||||
238
GTF/project/backend/node_modules/cors/lib/index.js
generated
vendored
Normal file
238
GTF/project/backend/node_modules/cors/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var assign = require('object-assign');
|
||||
var vary = require('vary');
|
||||
|
||||
var defaults = {
|
||||
origin: '*',
|
||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||
preflightContinue: false,
|
||||
optionsSuccessStatus: 204
|
||||
};
|
||||
|
||||
function isString(s) {
|
||||
return typeof s === 'string' || s instanceof String;
|
||||
}
|
||||
|
||||
function isOriginAllowed(origin, allowedOrigin) {
|
||||
if (Array.isArray(allowedOrigin)) {
|
||||
for (var i = 0; i < allowedOrigin.length; ++i) {
|
||||
if (isOriginAllowed(origin, allowedOrigin[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (isString(allowedOrigin)) {
|
||||
return origin === allowedOrigin;
|
||||
} else if (allowedOrigin instanceof RegExp) {
|
||||
return allowedOrigin.test(origin);
|
||||
} else {
|
||||
return !!allowedOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
function configureOrigin(options, req) {
|
||||
var requestOrigin = req.headers.origin,
|
||||
headers = [],
|
||||
isAllowed;
|
||||
|
||||
if (!options.origin || options.origin === '*') {
|
||||
// allow any origin
|
||||
headers.push([{
|
||||
key: 'Access-Control-Allow-Origin',
|
||||
value: '*'
|
||||
}]);
|
||||
} else if (isString(options.origin)) {
|
||||
// fixed origin
|
||||
headers.push([{
|
||||
key: 'Access-Control-Allow-Origin',
|
||||
value: options.origin
|
||||
}]);
|
||||
headers.push([{
|
||||
key: 'Vary',
|
||||
value: 'Origin'
|
||||
}]);
|
||||
} else {
|
||||
isAllowed = isOriginAllowed(requestOrigin, options.origin);
|
||||
// reflect origin
|
||||
headers.push([{
|
||||
key: 'Access-Control-Allow-Origin',
|
||||
value: isAllowed ? requestOrigin : false
|
||||
}]);
|
||||
headers.push([{
|
||||
key: 'Vary',
|
||||
value: 'Origin'
|
||||
}]);
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
function configureMethods(options) {
|
||||
var methods = options.methods;
|
||||
if (methods.join) {
|
||||
methods = options.methods.join(','); // .methods is an array, so turn it into a string
|
||||
}
|
||||
return {
|
||||
key: 'Access-Control-Allow-Methods',
|
||||
value: methods
|
||||
};
|
||||
}
|
||||
|
||||
function configureCredentials(options) {
|
||||
if (options.credentials === true) {
|
||||
return {
|
||||
key: 'Access-Control-Allow-Credentials',
|
||||
value: 'true'
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function configureAllowedHeaders(options, req) {
|
||||
var allowedHeaders = options.allowedHeaders || options.headers;
|
||||
var headers = [];
|
||||
|
||||
if (!allowedHeaders) {
|
||||
allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
|
||||
headers.push([{
|
||||
key: 'Vary',
|
||||
value: 'Access-Control-Request-Headers'
|
||||
}]);
|
||||
} else if (allowedHeaders.join) {
|
||||
allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
|
||||
}
|
||||
if (allowedHeaders && allowedHeaders.length) {
|
||||
headers.push([{
|
||||
key: 'Access-Control-Allow-Headers',
|
||||
value: allowedHeaders
|
||||
}]);
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
function configureExposedHeaders(options) {
|
||||
var headers = options.exposedHeaders;
|
||||
if (!headers) {
|
||||
return null;
|
||||
} else if (headers.join) {
|
||||
headers = headers.join(','); // .headers is an array, so turn it into a string
|
||||
}
|
||||
if (headers && headers.length) {
|
||||
return {
|
||||
key: 'Access-Control-Expose-Headers',
|
||||
value: headers
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function configureMaxAge(options) {
|
||||
var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
|
||||
if (maxAge && maxAge.length) {
|
||||
return {
|
||||
key: 'Access-Control-Max-Age',
|
||||
value: maxAge
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyHeaders(headers, res) {
|
||||
for (var i = 0, n = headers.length; i < n; i++) {
|
||||
var header = headers[i];
|
||||
if (header) {
|
||||
if (Array.isArray(header)) {
|
||||
applyHeaders(header, res);
|
||||
} else if (header.key === 'Vary' && header.value) {
|
||||
vary(res, header.value);
|
||||
} else if (header.value) {
|
||||
res.setHeader(header.key, header.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cors(options, req, res, next) {
|
||||
var headers = [],
|
||||
method = req.method && req.method.toUpperCase && req.method.toUpperCase();
|
||||
|
||||
if (method === 'OPTIONS') {
|
||||
// preflight
|
||||
headers.push(configureOrigin(options, req));
|
||||
headers.push(configureCredentials(options, req));
|
||||
headers.push(configureMethods(options, req));
|
||||
headers.push(configureAllowedHeaders(options, req));
|
||||
headers.push(configureMaxAge(options, req));
|
||||
headers.push(configureExposedHeaders(options, req));
|
||||
applyHeaders(headers, res);
|
||||
|
||||
if (options.preflightContinue) {
|
||||
next();
|
||||
} else {
|
||||
// Safari (and potentially other browsers) need content-length 0,
|
||||
// for 204 or they just hang waiting for a body
|
||||
res.statusCode = options.optionsSuccessStatus;
|
||||
res.setHeader('Content-Length', '0');
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
// actual response
|
||||
headers.push(configureOrigin(options, req));
|
||||
headers.push(configureCredentials(options, req));
|
||||
headers.push(configureExposedHeaders(options, req));
|
||||
applyHeaders(headers, res);
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
function middlewareWrapper(o) {
|
||||
// if options are static (either via defaults or custom options passed in), wrap in a function
|
||||
var optionsCallback = null;
|
||||
if (typeof o === 'function') {
|
||||
optionsCallback = o;
|
||||
} else {
|
||||
optionsCallback = function (req, cb) {
|
||||
cb(null, o);
|
||||
};
|
||||
}
|
||||
|
||||
return function corsMiddleware(req, res, next) {
|
||||
optionsCallback(req, function (err, options) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
var corsOptions = assign({}, defaults, options);
|
||||
var originCallback = null;
|
||||
if (corsOptions.origin && typeof corsOptions.origin === 'function') {
|
||||
originCallback = corsOptions.origin;
|
||||
} else if (corsOptions.origin) {
|
||||
originCallback = function (origin, cb) {
|
||||
cb(null, corsOptions.origin);
|
||||
};
|
||||
}
|
||||
|
||||
if (originCallback) {
|
||||
originCallback(req.headers.origin, function (err2, origin) {
|
||||
if (err2 || !origin) {
|
||||
next(err2);
|
||||
} else {
|
||||
corsOptions.origin = origin;
|
||||
cors(corsOptions, req, res, next);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// can pass either an options hash, an options delegate, or nothing
|
||||
module.exports = middlewareWrapper;
|
||||
|
||||
}());
|
||||
41
GTF/project/backend/node_modules/cors/package.json
generated
vendored
Normal file
41
GTF/project/backend/node_modules/cors/package.json
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "cors",
|
||||
"description": "Node.js CORS middleware",
|
||||
"version": "2.8.5",
|
||||
"author": "Troy Goode <troygoode@gmail.com> (https://github.com/troygoode/)",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cors",
|
||||
"express",
|
||||
"connect",
|
||||
"middleware"
|
||||
],
|
||||
"repository": "expressjs/cors",
|
||||
"main": "./lib/index.js",
|
||||
"dependencies": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"after": "0.8.2",
|
||||
"eslint": "2.13.1",
|
||||
"express": "4.16.3",
|
||||
"mocha": "5.2.0",
|
||||
"nyc": "13.1.0",
|
||||
"supertest": "3.3.0"
|
||||
},
|
||||
"files": [
|
||||
"lib/index.js",
|
||||
"CONTRIBUTING.md",
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env",
|
||||
"lint": "eslint lib test"
|
||||
}
|
||||
}
|
||||
90
GTF/project/backend/node_modules/object-assign/index.js
generated
vendored
Normal file
90
GTF/project/backend/node_modules/object-assign/index.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
/* eslint-disable no-unused-vars */
|
||||
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
||||
|
||||
function toObject(val) {
|
||||
if (val === null || val === undefined) {
|
||||
throw new TypeError('Object.assign cannot be called with null or undefined');
|
||||
}
|
||||
|
||||
return Object(val);
|
||||
}
|
||||
|
||||
function shouldUseNative() {
|
||||
try {
|
||||
if (!Object.assign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detect buggy property enumeration order in older V8 versions.
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
||||
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
|
||||
test1[5] = 'de';
|
||||
if (Object.getOwnPropertyNames(test1)[0] === '5') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||
var test2 = {};
|
||||
for (var i = 0; i < 10; i++) {
|
||||
test2['_' + String.fromCharCode(i)] = i;
|
||||
}
|
||||
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
|
||||
return test2[n];
|
||||
});
|
||||
if (order2.join('') !== '0123456789') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||
var test3 = {};
|
||||
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
|
||||
test3[letter] = letter;
|
||||
});
|
||||
if (Object.keys(Object.assign({}, test3)).join('') !==
|
||||
'abcdefghijklmnopqrst') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
// We don't expect any of the above to throw, but better to be safe.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = shouldUseNative() ? Object.assign : function (target, source) {
|
||||
var from;
|
||||
var to = toObject(target);
|
||||
var symbols;
|
||||
|
||||
for (var s = 1; s < arguments.length; s++) {
|
||||
from = Object(arguments[s]);
|
||||
|
||||
for (var key in from) {
|
||||
if (hasOwnProperty.call(from, key)) {
|
||||
to[key] = from[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (getOwnPropertySymbols) {
|
||||
symbols = getOwnPropertySymbols(from);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
if (propIsEnumerable.call(from, symbols[i])) {
|
||||
to[symbols[i]] = from[symbols[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
};
|
||||
21
GTF/project/backend/node_modules/object-assign/license
generated
vendored
Normal file
21
GTF/project/backend/node_modules/object-assign/license
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
42
GTF/project/backend/node_modules/object-assign/package.json
generated
vendored
Normal file
42
GTF/project/backend/node_modules/object-assign/package.json
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "object-assign",
|
||||
"version": "4.1.1",
|
||||
"description": "ES2015 `Object.assign()` ponyfill",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/object-assign",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava",
|
||||
"bench": "matcha bench.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"object",
|
||||
"assign",
|
||||
"extend",
|
||||
"properties",
|
||||
"es2015",
|
||||
"ecmascript",
|
||||
"harmony",
|
||||
"ponyfill",
|
||||
"prollyfill",
|
||||
"polyfill",
|
||||
"shim",
|
||||
"browser"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^0.16.0",
|
||||
"lodash": "^4.16.4",
|
||||
"matcha": "^0.7.0",
|
||||
"xo": "^0.16.0"
|
||||
}
|
||||
}
|
||||
61
GTF/project/backend/node_modules/object-assign/readme.md
generated
vendored
Normal file
61
GTF/project/backend/node_modules/object-assign/readme.md
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
# object-assign [](https://travis-ci.org/sindresorhus/object-assign)
|
||||
|
||||
> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
|
||||
|
||||
|
||||
## Use the built-in
|
||||
|
||||
Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
|
||||
support `Object.assign()` :tada:. If you target only those environments, then by all
|
||||
means, use `Object.assign()` instead of this package.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save object-assign
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const objectAssign = require('object-assign');
|
||||
|
||||
objectAssign({foo: 0}, {bar: 1});
|
||||
//=> {foo: 0, bar: 1}
|
||||
|
||||
// multiple sources
|
||||
objectAssign({foo: 0}, {bar: 1}, {baz: 2});
|
||||
//=> {foo: 0, bar: 1, baz: 2}
|
||||
|
||||
// overwrites equal keys
|
||||
objectAssign({foo: 0}, {foo: 1}, {foo: 2});
|
||||
//=> {foo: 2}
|
||||
|
||||
// ignores null and undefined sources
|
||||
objectAssign({foo: 0}, null, {bar: 1}, undefined);
|
||||
//=> {foo: 0, bar: 1}
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### objectAssign(target, [source, ...])
|
||||
|
||||
Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
23
GTF/project/backend/package-lock.json
generated
23
GTF/project/backend/package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.2",
|
||||
"express": "^5.1.0",
|
||||
"mssql": "^11.0.1"
|
||||
@@ -533,6 +534,19 @@
|
||||
"node": ">=6.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
@@ -1206,6 +1220,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.4",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.2",
|
||||
"express": "^5.1.0",
|
||||
"mssql": "^11.0.1"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
header("Content-Type: application/json");
|
||||
require_once "db.php";
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
$utilisateur_id = $data["utilisateur_id"];
|
||||
$type_demande_id = $data["type_demande_id"];
|
||||
$date = $data["date"];
|
||||
$duree = $data["duree"];
|
||||
$description = $data["description"] ?? null;
|
||||
$formateur_numero = $data["formateur_numero"];
|
||||
|
||||
$sql = "INSERT INTO declarations (utilisateur_id, type_demande_id, date, duree, description, formateur_numero)
|
||||
VALUES (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$params = [$utilisateur_id, $type_demande_id, $date, $duree, $description, $formateur_numero];
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt) {
|
||||
echo json_encode(["success" => true, "message" => "Déclaration enregistrée"]);
|
||||
} else {
|
||||
echo json_encode(["success" => false, "error" => sqlsrv_errors()]);
|
||||
}
|
||||
?>
|
||||
4
GTF/project/node_modules/.vite/deps/@azure_msal-browser.js
generated
vendored
4
GTF/project/node_modules/.vite/deps/@azure_msal-browser.js
generated
vendored
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
BrowserPerformanceMeasurement
|
||||
} from "./chunk-BXCAR3JX.js";
|
||||
} from "./chunk-5VK5IHOT.js";
|
||||
import {
|
||||
__export
|
||||
} from "./chunk-G3PMV62Z.js";
|
||||
@@ -16999,7 +16999,7 @@ function getPerfMeasurementModule() {
|
||||
sessionStorage = window[BrowserCacheLocation.SessionStorage];
|
||||
const perfEnabled = sessionStorage == null ? void 0 : sessionStorage.getItem(BROWSER_PERF_ENABLED_KEY);
|
||||
if (Number(perfEnabled) === 1) {
|
||||
return import("./BrowserPerformanceMeasurement-5UJNI4WV.js");
|
||||
return import("./BrowserPerformanceMeasurement-5VDOVMRB.js");
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map
generated
vendored
2
GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
BrowserPerformanceMeasurement
|
||||
} from "./chunk-BXCAR3JX.js";
|
||||
} from "./chunk-5VK5IHOT.js";
|
||||
import "./chunk-G3PMV62Z.js";
|
||||
export {
|
||||
BrowserPerformanceMeasurement
|
||||
};
|
||||
//# sourceMappingURL=BrowserPerformanceMeasurement-5UJNI4WV.js.map
|
||||
//# sourceMappingURL=BrowserPerformanceMeasurement-5VDOVMRB.js.map
|
||||
46
GTF/project/node_modules/.vite/deps/_metadata.json
generated
vendored
46
GTF/project/node_modules/.vite/deps/_metadata.json
generated
vendored
@@ -1,58 +1,58 @@
|
||||
{
|
||||
"hash": "0db3536e",
|
||||
"configHash": "dc00d83f",
|
||||
"lockfileHash": "14011340",
|
||||
"browserHash": "672592a0",
|
||||
"hash": "1e9c2bee",
|
||||
"configHash": "451161ff",
|
||||
"lockfileHash": "b1ec30a4",
|
||||
"browserHash": "57e609ed",
|
||||
"optimized": {
|
||||
"react": {
|
||||
"src": "../../react/index.js",
|
||||
"file": "react.js",
|
||||
"fileHash": "8ad7db99",
|
||||
"fileHash": "4348729b",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-dev-runtime": {
|
||||
"src": "../../react/jsx-dev-runtime.js",
|
||||
"file": "react_jsx-dev-runtime.js",
|
||||
"fileHash": "ec7323e1",
|
||||
"fileHash": "9694e297",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-runtime": {
|
||||
"src": "../../react/jsx-runtime.js",
|
||||
"file": "react_jsx-runtime.js",
|
||||
"fileHash": "7307506d",
|
||||
"fileHash": "4fa96245",
|
||||
"needsInterop": true
|
||||
},
|
||||
"@azure/msal-browser": {
|
||||
"src": "../../@azure/msal-browser/dist/index.mjs",
|
||||
"file": "@azure_msal-browser.js",
|
||||
"fileHash": "8be31f82",
|
||||
"needsInterop": false
|
||||
},
|
||||
"react-dom/client": {
|
||||
"src": "../../react-dom/client.js",
|
||||
"file": "react-dom_client.js",
|
||||
"fileHash": "e3d0ad6f",
|
||||
"fileHash": "8aa9b52d",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-router-dom": {
|
||||
"src": "../../../../node_modules/react-router-dom/dist/index.mjs",
|
||||
"file": "react-router-dom.js",
|
||||
"fileHash": "ca3428cd",
|
||||
"needsInterop": false
|
||||
},
|
||||
"@azure/msal-browser": {
|
||||
"src": "../../@azure/msal-browser/dist/index.mjs",
|
||||
"file": "@azure_msal-browser.js",
|
||||
"fileHash": "72740ae2",
|
||||
"fileHash": "f4ac1124",
|
||||
"needsInterop": false
|
||||
}
|
||||
},
|
||||
"chunks": {
|
||||
"chunk-6BKLQ22S": {
|
||||
"file": "chunk-6BKLQ22S.js"
|
||||
"chunk-4W2RIJ36": {
|
||||
"file": "chunk-4W2RIJ36.js"
|
||||
},
|
||||
"chunk-DRWLMN53": {
|
||||
"file": "chunk-DRWLMN53.js"
|
||||
"chunk-QRULMDK5": {
|
||||
"file": "chunk-QRULMDK5.js"
|
||||
},
|
||||
"BrowserPerformanceMeasurement-5UJNI4WV": {
|
||||
"file": "BrowserPerformanceMeasurement-5UJNI4WV.js"
|
||||
"BrowserPerformanceMeasurement-5VDOVMRB": {
|
||||
"file": "BrowserPerformanceMeasurement-5VDOVMRB.js"
|
||||
},
|
||||
"chunk-BXCAR3JX": {
|
||||
"file": "chunk-BXCAR3JX.js"
|
||||
"chunk-5VK5IHOT": {
|
||||
"file": "chunk-5VK5IHOT.js"
|
||||
},
|
||||
"chunk-G3PMV62Z": {
|
||||
"file": "chunk-G3PMV62Z.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
require_react
|
||||
} from "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-QRULMDK5.js";
|
||||
import {
|
||||
__commonJS
|
||||
} from "./chunk-G3PMV62Z.js";
|
||||
@@ -21626,4 +21626,4 @@ react-dom/cjs/react-dom.development.js:
|
||||
* @license Modernizr 3.0.0pre (Custom Build) | MIT
|
||||
*)
|
||||
*/
|
||||
//# sourceMappingURL=chunk-6BKLQ22S.js.map
|
||||
//# sourceMappingURL=chunk-4W2RIJ36.js.map
|
||||
7
GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js.map
generated
vendored
Normal file
7
GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -82,4 +82,4 @@ export {
|
||||
@azure/msal-browser/dist/telemetry/BrowserPerformanceMeasurement.mjs:
|
||||
(*! @azure/msal-browser v4.22.1 2025-09-09 *)
|
||||
*/
|
||||
//# sourceMappingURL=chunk-BXCAR3JX.js.map
|
||||
//# sourceMappingURL=chunk-5VK5IHOT.js.map
|
||||
7
GTF/project/node_modules/.vite/deps/chunk-5VK5IHOT.js.map
generated
vendored
Normal file
7
GTF/project/node_modules/.vite/deps/chunk-5VK5IHOT.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
7
GTF/project/node_modules/.vite/deps/chunk-6BKLQ22S.js.map
generated
vendored
7
GTF/project/node_modules/.vite/deps/chunk-6BKLQ22S.js.map
generated
vendored
File diff suppressed because one or more lines are too long
7
GTF/project/node_modules/.vite/deps/chunk-BXCAR3JX.js.map
generated
vendored
7
GTF/project/node_modules/.vite/deps/chunk-BXCAR3JX.js.map
generated
vendored
File diff suppressed because one or more lines are too long
7
GTF/project/node_modules/.vite/deps/chunk-DRWLMN53.js.map
generated
vendored
7
GTF/project/node_modules/.vite/deps/chunk-DRWLMN53.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1903,4 +1903,4 @@ react/cjs/react.development.js:
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
*/
|
||||
//# sourceMappingURL=chunk-DRWLMN53.js.map
|
||||
//# sourceMappingURL=chunk-QRULMDK5.js.map
|
||||
7
GTF/project/node_modules/.vite/deps/chunk-QRULMDK5.js.map
generated
vendored
Normal file
7
GTF/project/node_modules/.vite/deps/chunk-QRULMDK5.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
4
GTF/project/node_modules/.vite/deps/react-dom_client.js
generated
vendored
4
GTF/project/node_modules/.vite/deps/react-dom_client.js
generated
vendored
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
require_react_dom
|
||||
} from "./chunk-6BKLQ22S.js";
|
||||
import "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-4W2RIJ36.js";
|
||||
import "./chunk-QRULMDK5.js";
|
||||
import {
|
||||
__commonJS
|
||||
} from "./chunk-G3PMV62Z.js";
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/react-dom_client.js.map
generated
vendored
2
GTF/project/node_modules/.vite/deps/react-dom_client.js.map
generated
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../react-dom/client.js"],
|
||||
"sourcesContent": ["'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n"],
|
||||
"sourcesContent": ["'use strict';\r\n\r\nvar m = require('react-dom');\r\nif (process.env.NODE_ENV === 'production') {\r\n exports.createRoot = m.createRoot;\r\n exports.hydrateRoot = m.hydrateRoot;\r\n} else {\r\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\r\n exports.createRoot = function(c, o) {\r\n i.usingClientEntryPoint = true;\r\n try {\r\n return m.createRoot(c, o);\r\n } finally {\r\n i.usingClientEntryPoint = false;\r\n }\r\n };\r\n exports.hydrateRoot = function(c, h, o) {\r\n i.usingClientEntryPoint = true;\r\n try {\r\n return m.hydrateRoot(c, h, o);\r\n } finally {\r\n i.usingClientEntryPoint = false;\r\n }\r\n };\r\n}\r\n"],
|
||||
"mappings": ";;;;;;;;;AAAA;AAAA;AAEA,QAAI,IAAI;AACR,QAAI,OAAuC;AACzC,cAAQ,aAAa,EAAE;AACvB,cAAQ,cAAc,EAAE;AAAA,IAC1B,OAAO;AACD,UAAI,EAAE;AACV,cAAQ,aAAa,SAAS,GAAG,GAAG;AAClC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,WAAW,GAAG,CAAC;AAAA,QAC1B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AACA,cAAQ,cAAc,SAAS,GAAG,GAAG,GAAG;AACtC,UAAE,wBAAwB;AAC1B,YAAI;AACF,iBAAO,EAAE,YAAY,GAAG,GAAG,CAAC;AAAA,QAC9B,UAAE;AACA,YAAE,wBAAwB;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAjBM;AAAA;AAAA;",
|
||||
"names": []
|
||||
}
|
||||
|
||||
4
GTF/project/node_modules/.vite/deps/react-router-dom.js
generated
vendored
4
GTF/project/node_modules/.vite/deps/react-router-dom.js
generated
vendored
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
require_react_dom
|
||||
} from "./chunk-6BKLQ22S.js";
|
||||
} from "./chunk-4W2RIJ36.js";
|
||||
import {
|
||||
require_react
|
||||
} from "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-QRULMDK5.js";
|
||||
import {
|
||||
__commonJS,
|
||||
__toESM
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/react-router-dom.js.map
generated
vendored
2
GTF/project/node_modules/.vite/deps/react-router-dom.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2
GTF/project/node_modules/.vite/deps/react.js
generated
vendored
2
GTF/project/node_modules/.vite/deps/react.js
generated
vendored
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
require_react
|
||||
} from "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-QRULMDK5.js";
|
||||
import "./chunk-G3PMV62Z.js";
|
||||
export default require_react();
|
||||
//# sourceMappingURL=react.js.map
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/react_jsx-dev-runtime.js
generated
vendored
2
GTF/project/node_modules/.vite/deps/react_jsx-dev-runtime.js
generated
vendored
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
require_react
|
||||
} from "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-QRULMDK5.js";
|
||||
import {
|
||||
__commonJS
|
||||
} from "./chunk-G3PMV62Z.js";
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/react_jsx-dev-runtime.js.map
generated
vendored
2
GTF/project/node_modules/.vite/deps/react_jsx-dev-runtime.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2
GTF/project/node_modules/.vite/deps/react_jsx-runtime.js
generated
vendored
2
GTF/project/node_modules/.vite/deps/react_jsx-runtime.js
generated
vendored
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
require_react
|
||||
} from "./chunk-DRWLMN53.js";
|
||||
} from "./chunk-QRULMDK5.js";
|
||||
import {
|
||||
__commonJS
|
||||
} from "./chunk-G3PMV62Z.js";
|
||||
|
||||
2
GTF/project/node_modules/.vite/deps/react_jsx-runtime.js.map
generated
vendored
2
GTF/project/node_modules/.vite/deps/react_jsx-runtime.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Calendar from './components/Calendar';
|
||||
import TimeEntryModal from './components/TimeEntryModal';
|
||||
import UserProfile from './components/UserProfile';
|
||||
@@ -7,24 +7,55 @@ import { Clock, User, Calendar as CalendarIcon, Menu, X, LogOut } from 'lucide-r
|
||||
import { useAuth } from './context/AuthContext';
|
||||
|
||||
function App() {
|
||||
const { logout, user } = useAuth(); // récupère user depuis AuthContext
|
||||
const { logout, user } = useAuth();
|
||||
const [selectedDate, setSelectedDate] = useState<string | null>(null);
|
||||
const [timeEntries, setTimeEntries] = useState<TimeEntry[]>([]);
|
||||
const [showProfile, setShowProfile] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Fonction pour charger les déclarations depuis la base
|
||||
const loadDeclarations = async () => {
|
||||
try {
|
||||
console.log('Chargement des déclarations...');
|
||||
const response = await fetch('http://localhost:3001/api/get_declarations');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Déclarations reçues:', data);
|
||||
|
||||
// Convertir les données du serveur au format TimeEntry
|
||||
const entries: TimeEntry[] = data.map((d: any) => ({
|
||||
date: d.date.split('T')[0], // Convertir la date SQL en format YYYY-MM-DD
|
||||
activityType: d.activityType,
|
||||
hours: d.duree,
|
||||
description: d.description || '',
|
||||
createdAt: new Date(d.date)
|
||||
}));
|
||||
|
||||
setTimeEntries(entries);
|
||||
console.log('Déclarations converties:', entries);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des déclarations:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Charger les déclarations au démarrage
|
||||
useEffect(() => {
|
||||
loadDeclarations();
|
||||
}, []);
|
||||
|
||||
const handleDateClick = (date: string) => setSelectedDate(date);
|
||||
const handleCloseModal = () => setSelectedDate(null);
|
||||
|
||||
const handleSaveEntry = (entry: TimeEntry) => {
|
||||
setTimeEntries(prev => {
|
||||
const existingIndex = prev.findIndex(e => e.date === entry.date);
|
||||
if (existingIndex >= 0) {
|
||||
const updated = [...prev];
|
||||
updated[existingIndex] = entry;
|
||||
return updated;
|
||||
}
|
||||
return [...prev, entry];
|
||||
});
|
||||
const handleSaveEntry = async (entry: TimeEntry) => {
|
||||
console.log('Sauvegarde réussie, rechargement des données...');
|
||||
// Recharger les données depuis la base après sauvegarde
|
||||
await loadDeclarations();
|
||||
setSelectedDate(null);
|
||||
};
|
||||
|
||||
@@ -121,10 +152,17 @@ function App() {
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6 sm:gap-8">
|
||||
{/* Calendar - Main Section */}
|
||||
<div className="xl:col-span-2">
|
||||
{loading ? (
|
||||
<div className="bg-white rounded-2xl shadow-xl border border-gray-100 p-8 text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-4"></div>
|
||||
<div className="text-gray-600">Chargement des déclarations...</div>
|
||||
</div>
|
||||
) : (
|
||||
<Calendar
|
||||
onDateClick={handleDateClick}
|
||||
getEntryForDate={getEntryForDate}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
@@ -153,8 +191,9 @@ function App() {
|
||||
<button
|
||||
onClick={() => handleDateClick(new Date().toISOString().split('T')[0])}
|
||||
className="w-full p-3 bg-blue-50 hover:bg-blue-100 text-blue-700 font-medium rounded-lg transition-colors text-left"
|
||||
disabled={loading}
|
||||
>
|
||||
Déclarer aujourd'hui
|
||||
{loading ? 'Chargement...' : 'Déclarer aujourd\'hui'}
|
||||
</button>
|
||||
|
||||
<div className="text-sm text-gray-600">
|
||||
@@ -168,7 +207,7 @@ function App() {
|
||||
</div>
|
||||
|
||||
{/* Recent Entries */}
|
||||
{timeEntries.length > 0 && (
|
||||
{!loading && timeEntries.length > 0 && (
|
||||
<div className="bg-white rounded-2xl shadow-lg p-4 sm:p-6 border border-gray-100">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
|
||||
<Clock className="h-5 w-5 text-green-600" />
|
||||
@@ -206,6 +245,20 @@ function App() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* No Data Message */}
|
||||
{!loading && timeEntries.length === 0 && (
|
||||
<div className="bg-white rounded-2xl shadow-lg p-4 sm:p-6 border border-gray-100 text-center">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-2">Aucune déclaration</h3>
|
||||
<p className="text-sm text-gray-600 mb-4">Commencez par déclarer vos premières heures</p>
|
||||
<button
|
||||
onClick={() => handleDateClick(new Date().toISOString().split('T')[0])}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
Déclarer maintenant
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Help Section */}
|
||||
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-2xl p-4 sm:p-6 border border-blue-100">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-3">
|
||||
@@ -222,7 +275,7 @@ function App() {
|
||||
</div>
|
||||
|
||||
{/* Modal */}
|
||||
{selectedDate && (
|
||||
{selectedDate && !loading && (
|
||||
<TimeEntryModal
|
||||
date={selectedDate}
|
||||
existingEntry={getEntryForDate(selectedDate)}
|
||||
|
||||
@@ -39,7 +39,7 @@ const Calendar: React.FC<CalendarProps> = ({ onDateClick, getEntryForDate }) =>
|
||||
|
||||
// Charger les déclarations depuis PHP
|
||||
useEffect(() => {
|
||||
fetch("http://localhost/GTF/project/backend/get_declarations.php")
|
||||
fetch("http://localhost:3001/api/get_declarations")
|
||||
.then((res) => res.json())
|
||||
.then((data) => setDeclarations(data))
|
||||
.catch((err) => console.error("Erreur fetch:", err));
|
||||
@@ -47,7 +47,7 @@ const Calendar: React.FC<CalendarProps> = ({ onDateClick, getEntryForDate }) =>
|
||||
|
||||
// Fonction de sauvegarde d'une déclaration (à utiliser selon besoin)
|
||||
const saveDeclaration = async (newDeclaration: Declaration) => {
|
||||
const res = await fetch("http://localhost/GTF/project/backend/save_declaration.php", {
|
||||
const res = await fetch("http://localhost:3001/api/get_declarations", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(newDeclaration),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { X, Clock, FileText, Save, AlertCircle } from 'lucide-react';
|
||||
import { TimeEntry } from '../types/TimeEntry';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
interface TimeEntryModalProps {
|
||||
date: string;
|
||||
@@ -20,6 +21,10 @@ const TimeEntryModal: React.FC<TimeEntryModalProps> = ({
|
||||
const [description, setDescription] = useState('');
|
||||
const [errors, setErrors] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { user, isAuthorized } = useAuth();
|
||||
|
||||
console.log('DEBUG AUTH:', { user, isAuthorized });
|
||||
console.log('user est:', typeof user, user);
|
||||
|
||||
useEffect(() => {
|
||||
if (existingEntry) {
|
||||
@@ -65,10 +70,23 @@ const TimeEntryModal: React.FC<TimeEntryModalProps> = ({
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch("http://localhost/GTF/project/backend/save_declaration.php", {
|
||||
console.log('Utilisateur connecté:', user);
|
||||
console.log('Données à envoyer:', {
|
||||
...entry,
|
||||
user: user
|
||||
});
|
||||
|
||||
|
||||
const response = await fetch("http://localhost:3001/api/save_declaration", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(entry),
|
||||
body: JSON.stringify({
|
||||
date: date,
|
||||
activityType: activityType,
|
||||
hours: hours,
|
||||
description: description.trim(),
|
||||
user: user
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorMsg = await response.text();
|
||||
|
||||
Reference in New Issue
Block a user