back-end
continuous-integration/drone/push Build encountered an error Details

pull/1/head
Noan07 3 years ago
parent 419a33cb02
commit 69aba5523a

@ -1,23 +1,2 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/config/.env

@ -0,0 +1,2 @@
REACT_APP_API_URL=http://localhost:5000/
# Lors du déploiment du site il faudra changer url

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

File diff suppressed because it is too large Load Diff

@ -0,0 +1,43 @@
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.1.3",
"dotenv": "^16.0.3",
"node-sass": "^7.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.2",
"react-scripts": "5.0.1",
"tachyons": "^4.12.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> -->
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

@ -0,0 +1,47 @@
import Routes from "./components/Routes";
import { UidContext } from "./components/AppContext";
import { useEffect, useState } from "react";
import axios from "axios";
//useeffect controle le token de l'utilisateur
//les crochets dans le use effect permette de pas lancer la fonction à l'infini
function App() {
const [uid, setUid] = useState(null);
useEffect(() => {
const fetchToken = async() => {
await axios({
method: "get",
url: `${process.env.REACT_APP_API_URL}jwtid`,
withCredentials: true,
})
.then((res) => setUid(res.data))
.catch((err) => console.log("No Token"));
};
fetchToken();
}, [uid]);
return (
<UidContext.Provider value={uid}>
<Routes />
</UidContext.Provider>
);
}
export default App;
/*<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>*/

@ -0,0 +1,4 @@
import { createContext } from "react";
//bien pour stocker un element sinon utiliser redux
export const UidContext = createContext();

@ -0,0 +1,82 @@
import axios from 'axios';
import React, { useState } from 'react';
//e.preventDefaul(); pour ne pas recharcher la page
const Connexion = (props) => {
const [errorMessage] = useState(props.error);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = (e) => {
e.preventDefault();
const emailError = document.querySelector('.email.error');
const passwordError = document.querySelector('.password.error');
axios({
method: "post",
url:`${process.env.REACT_APP_API_URL}api/user/login`,
withCredentials: true,
data: {
email,
password,
},
})
.then((res) => {
if(res.data.errors){
emailError.innerHTML = res.data.errors.email;
passwordError.innerHTML = res.data.errors.password
} else {
window.location = "/";
}
})
.catch((err) => {
console.log(err);
})
};
return (
<div className='formulaire'>
<form className='cadre' action='' onSubmit={handleLogin} id="sign-up-form">
<h1>Connexion</h1>
<div className='inputbox'>
<input
type="text"
name="email"
id="email"
onChange={(e) => setEmail (e.target.value)}
value={email}/>
<span>email</span>
</div>
<div className="email error"></div>
<br />
<div className="inputbox">
<input
type="password"
name="password"
id="password"
onChange={(e) => setPassword (e.target.value)}
value={password}/>
<span>mot de passe</span>
</div>
<div className="password error"></div>
<br />
<input type="submit" value="connexion" id='connexion' />
<br/>
<p className='mdp'>Mot de passe oublié?</p>
<br />
{errorMessage && <h4 className='success'>
Enregistrement réussi, veuillez-vous connecter
</h4>}
</form>
</div>
);
};
//ce qui écrit dans le input est récuperé par le state
export default Connexion;

@ -0,0 +1,129 @@
import React, { useState } from 'react';
import axios from "axios";
import Connexion from "./Connexion";
const Inscription = () => {
const [formSubmit, setFormSubmit] = useState(false);
const [pseudo, setPseudo] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [controlPassword, setControlPassword] = useState('');
const handleRegister = async (e) => {
console.log("test");
e.preventDefault();
const terms = document.getElementById("terms");
const pseudoError = document.querySelector(".pseudo.error");
const emailError = document.querySelector(".email.error");
const passwordError = document.querySelector(".password.error");
const passwordConfirmError = document.querySelector(
".password-confirm.error"
);
const termsError = document.querySelector(".terms.error");
passwordConfirmError.innerHTML = "";
termsError.innerHTML = "";
if (password !== controlPassword || !terms.checked) {
if (password !== controlPassword)
passwordConfirmError.innerHTML = "Les mots de passe ne correspondent pas";
if (!terms.checked)
termsError.innerHTML = "Veuillez valider les conditions générales";
} else {
await axios({
method: "post",
url: `${process.env.REACT_APP_API_URL}api/user/register`,
data: {
pseudo,
email,
password,
},
})
.then((res) => {
console.log(res);
if (res.data.errors) {
pseudoError.innerHTML = res.data.errors.pseudo;
emailError.innerHTML = res.data.errors.email;
passwordError.innerHTML = res.data.errors.password;
} else {
setFormSubmit(true);
}
})
.catch((err) => console.log(err));
}
};
return (
<>
{formSubmit ? (
<div className='enregistrementReussi'>
<Connexion error={true} />
</div>
) : (
<div className="formulaire">
<form className="cadre" action='' onSubmit={handleRegister}>
<h1>Inscription</h1>
<div className="inputbox">
<input type="text"
name="pseudo"
id="pseudo"
onChange={(e) => setPseudo(e.target.value)}
value={pseudo}/>
<span>pseudo</span>
</div>
<div className='pseudo error'></div>
<br />
<div className="inputbox">
<input type="text"
name="email"
id="email"
onChange={(e) => setEmail(e.target.value)}
value={email}/>
<span>email</span>
</div>
<div className='email error'></div>
<br />
<div className="inputbox">
<input type="password"
name="password"
id="password"
onChange={(e) => setPassword(e.target.value)}
value={password}/>
<span>mot de passe</span>
</div>
<div className='password error'></div>
<br />
<div className="inputbox">
<input type="password"
name="password"
id="password-conf"
onChange={(e) => setControlPassword(e.target.value)}
value={controlPassword}/>
<span>comfirmation mot de passe</span>
</div>
<div className='password-confirm error'></div>
<br />
<div className="chexkboxConditionGenerale">
<input type="checkbox"
name="terms"
id="terms"/>
<span>J'accepte les <a href="/" target="_blank" rel='noopener noreferrer'>conditions générales</a></span>
</div>
<div className="terms error"></div>
<br />
<input type="submit" value="inscription" id="inscription"/>
</form>
</div>
)}
</>
);
};
export default Inscription;

@ -0,0 +1,61 @@
import React, { useState } from 'react'
import Connexion from './Connexion';
import Inscription from './Inscription';
import '../../styles/pages/_profil.scss'
const Log = ( props ) => {
const [signUpModal, setSignUpModal] = useState(props.signup);
const [signInModal, setSignInModal] = useState(props.signin);
const handleModals = (e) => {
if (e.target.id === "register") {
setSignInModal(false);
setSignUpModal(true);
} else if (e.target.id === "login") {
setSignUpModal(false);
setSignInModal(true);
}
};
return (
<div className="connection-form">
<div className="form-container">
<div className="info-form-container">
<ul>
<li className='info-form-right'>Bienvenue !</li>
<li className='info-form-right'>
<div className='description-type-connection'>
<p>Vous ne disposez pas</p>
<p>de compte</p>
</div>
</li>
<li
onClick={handleModals}
id="register"
className={signUpModal ? "active-btn button-form" : "button-form"}
>
S'inscrire
</li>
<li className='info-form-right'>
<div className='description-type-connection'>
<p>Vous possédez déjà</p>
<p>un compte</p>
</div>
</li>
<li
onClick={handleModals}
id="login"
className={signInModal ? "active-btn button-form" : "button-form"}
>
Se connecter
</li>
</ul>
</div>
{signUpModal && <Inscription />}
{signInModal && <Connexion />}
</div>
</div>
);
};
export default Log;

@ -0,0 +1,15 @@
import React from 'react';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Profil from '../../pages/Profil.js'
const index = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Profil/>} />
</Routes>
</BrowserRouter>
);
};
export default index;

@ -1,6 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './styles/index.scss';
import App from './App';
import "./styles/index.scss";
@ -11,4 +10,3 @@ root.render(
</React.StrictMode>
);

@ -0,0 +1,22 @@
import React, { useContext } from 'react';
import { UidContext } from '../components/AppContext';
import Log from '../components/Log'
import '../styles/pages/_profil.scss'
const Profil = () => {
const uid = useContext(UidContext);
return (
<div className="profil-page">
{uid ? (
<h1>UPDATE PAGE</h1>
) : (
<div className="log-container">
<Log signin={true} signup={false}/>
</div>
)}
</div>
);
};
export default Profil;

@ -0,0 +1,2 @@
@import './_settings.scss';
@import './pages/profil';

@ -0,0 +1,160 @@
$color-1: #A4EBF3;
$color-2: #CCF2F4;
$color-3: #F4F9F9;
$color-4: #AAAAAA;
ul{
list-style-type: none;
display: flex;
flex-direction: column;
align-items: center;
.button-form{
cursor: pointer;
border: 3px solid black;
border-radius: 20px;
padding: 10px 20px;
transition: 0.2s;
width: 150px;
height: 45px;
text-align: center;
margin-top: 10px;
}
.active-btn {
background: $color-1;
&:hover {
background: $color-2;
}
}
.button-form:not(.active-btn) {
&:hover {
transform: translateX(3px);
}
}
}
.info-form-container{
width: 20%;
border: 2px solid black;
border-radius: 0px 15px 15px 0px;
background-color: aliceblue;
p{
line-height: 15px;
letter-spacing: 1.01px;
}
}
.profile-page{
width: 100%;
}
.form-container{
display: flex;
flex-direction: row-reverse;
justify-content: center;
padding-top: 2%;
}
.description-type-connection{
text-align: center;
}
.cadre {
padding: 50px 50px;
border: 2px solid black;
border-right: 0px solid black;
border-radius: 15px 0px 0px 15px;
background-color: $color-1;
h1 {
letter-spacing: 5px;
margin-bottom: 60px;
font-weight: bold;
text-align: center;
}
.inputbox {
position: relative;
width: 300px;
margin-top: 25px;
input {
width: 100%;
border: 2px solid #000;
outline: none;
background-color: $color-3;
padding: 10px;
border-radius: 10px;
font-size: 1.1em;
}
span {
position: absolute;
top: 14px;
left: 20px;
font-size: 1em;
transition: 0.3s;
font-family: sans-serif;
}
}
.chexkboxConditionGenerale{
margin-top: 3px;
padding: 5px;
}
.error{
padding-left: 5px;
font-size: small;
font-weight: 600;
color: red;
position: absolute;
}
#connexion,#inscription{
margin-top: 5px;
}
}
.span_date{
margin-left: 7px;
font-size: 1em;
font-family: sans-serif;
}
.cadre .inputbox input:focus ~ span,
.cadre .inputbox input:valid ~ span {
transform: translateX(-13px) translateY(-35px);
font-size: 1em;
}
input[type="submit"], .buttonTEL{
border: none;
border-radius: 8px;
border: 2px solid #000;
background-color: $color-3;
width: 300px;
height: 50px;
}
.buttonTEL{
margin-top: 15px;
margin-bottom: 15px;
}
input[type="submit"]:hover, .buttonTEL:hover{
background-color: $color-4;
}
.mdp{
font-weight: 900;
}
.info-form-container{
.info-form-right{
padding-top: 15px;
}
}
.enregistrementReussi{
display: flex;
flex-direction: column;
}

@ -0,0 +1,9 @@
const mongoose = require("mongoose");
mongoose
.connect(
"mongodb+srv://" + process.env.DB_USER_PASS + "@cluster0.otbghne.mongodb.net/test",
{}
)
.then(() => console.log('Connected to MongoDB'))
.catch((err) => console.log("Failed to connect to MongoDB", err));

@ -0,0 +1,50 @@
const UserModel = require('../models/user.model');
const jwt = require('jsonwebtoken');
const { signUpErrors, signInErrors } = require('../utils/errors.utils');
const maxAge = 3 * 24 * 60 * 60 * 1000;
//expiresIn temps avant l'expiration du token
const createToken = (id) => {
return jwt.sign({id}, process.env.TOKEN_SECRET, {
expiresIn: maxAge
})
}
//gestion des erreurs
module.exports.signUp = async (req, res) => {
//Attention à enlever
const {pseudo, email, password} = req.body
try {
const user = await UserModel.create({pseudo, email, password});
res.status(201).json({ user: user._id});
}
catch(err) {
const errors = signUpErrors(err);
res.status(200).send({ errors })
}
}
module.exports.signIn = async (req, res) => {
//console.log(req.body);
const {email, password} = req.body
try {
const user = await UserModel.login({email, password});
//creation d'un token
const token = createToken(user._id);
res.cookie('jwt', token, { httpOnly: true, maxAge});
res.status(200).json({ user: user._id});
}
catch(err) {
const errors = signInErrors(err);
res.status(200).send({ errors });
}
}
module.exports.logout = async (req, res) => {
res.cookie('jwt', '', { maxAge: 1});
res.redirect('/');
}

@ -0,0 +1,106 @@
const UserModel = require("../models/user.model");
const ObjectID = require("mongoose").Types.ObjectId;
//-password pour ne pas donner le password
module.exports.getAllUsers = async (req, res) => {
const users = await UserModel.find().select("-password");
res.status(200).json(users);
};
//req.params par url
module.exports.userInfo = (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
UserModel.findById(req.params.id, (err, docs) => {
if (!err) res.send(docs);
else console.log("ID unknown : " + err);
}).select("-password");
};
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true })
.then((data) => res.send(data))
.catch((err) => res.status(500).send({ message: err }));
} catch (err) {
return res.status(500).json({ message: err });
}
};
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.remove({ _id: req.params.id }).exec();
res.status(200).json({ message: "Successfully deleted. " });
} catch (err) {
return res.status(500).json({ message: err });
}
};
module.exports.follow = async (req, res) => {
if (
!ObjectID.isValid(req.params.id) ||
!ObjectID.isValid(req.body.idToFollow)
)
return res.status(400).send("ID unknown : " + req.params.id);
try {
// add to the follower list
await UserModel.findByIdAndUpdate(
req.params.id,
{ $addToSet: { following: req.body.idToFollow } },
{ new: true, upsert: true }
.then((data) => res.send(data))
.catch((err) => res.status(500).send({ message: err }))),
// ajouter à la liste des followers
await UserModel.findByIdAndUpdate(
req.body.idToFollow,
{ $addToSet: { followers: req.params.id } },
{ new: true, upsert: true }
.then((data) => res.send(data))
.catch((err) => res.status(500).send({ message: err })))
} catch (err) {
return res.status(500).json({ message: err });
}
};
module.exports.unfollow = async (req, res) => {
if (
!ObjectID.isValid(req.params.id) ||
!ObjectID.isValid(req.body.idToUnfollow)
)
return res.status(400).send("ID unknown : " + req.params.id);
try {
await userModel.findByIdAndUpdate(
req.params.id,
{ $pull: { following: req.body.idToUnfollow } },
{ new: true, upsert: true }
.then((data) => res.send(data))
.catch((err) => res.status(500).send({ message: err }))),
// Retirer de la liste des followers
await userModel.findByIdAndUpdate(
req.body.idToUnfollow,
{ $pull: { followers: req.params.id } },
{ new: true, upsert: true }
.then((data) => res.send(data))
.catch((err) => res.status(500).send({ message: err })))
} catch (err) {
return res.status(500).json({ message: err });
}
}

@ -0,0 +1,40 @@
const jwt = require('jsonwebtoken');
const UserModel = require('../models/user.model');
module.exports.checkUser = (req, res, next) => {
const token = req.cookies.jwt;
console.log("test");
if(token) {
jwt.verify(token, process.env.TOKEN_SECRET, async (err, decodedToken) => {
if (err) {
res.locals.user = null;
res.cookie('jwt', '', { maxAge: 1 });
next();
} else {
let user = await UserModel.findById(decodedToken.id);
res.locals.user = user;
next();
}
})
}else {
res.locals.user = null;
next();
}
}
module.exports.requireAuth = (req, res, next) => {
const token = req.cookies.jwt;
if (token) {
jwt.verify(token, process.env.TOKEN_SECRET, async (err, decodedToken) => {
if (err) {
console.log(err);
res.send(200).json('no token')
} else {
console.log(decodedToken.id);
next();
}
});
} else {
console.log('No token');
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,80 @@
const mongoose = require('mongoose');
//pour vérifier la validité d'une adresse mail
const { isEmail } = require('validator');
const bcrypt = require('bcrypt');
//trim pour supprimer les espaces
const userSchema = new mongoose.Schema(
{
pseudo: {
type: String,
required: true,
minLength: 3,
maxLength: 55,
unique: true,
trim: true
},
email: {
type: String,
required: true,
validate: [isEmail],
lowercase: true,
unique: true,
trim: true
},
password: {
type: String,
required: true,
max: 1024,
minlength: 6
},
picture: {
type: String,
default: "/random-user.png"
},
bio :{
type: String,
max: 1024,
},
followers: {
type: [String]
},
following: {
type: [String]
},
likes: {
type: [String]
}
},
{
timestamps: true,
}
);
//timestamps pour savoir quand l'utilisateur c'est connecté
// play function before save into display: 'block',
userSchema.pre("save", async function(next) {
const salt = await bcrypt.genSalt();
this.password = await bcrypt.hash(this.password, salt);
next();
});
userSchema.statics.login = async function({email, password}) {
const user = await this.findOne( {email} );
console.log(user);
if (user) {
const auth = await bcrypt.compare(password, user.password);
if (auth) {
return user;
}
throw Error('incorrect password');
}
throw Error('incorrect email')
};
const UserModel = mongoose.model("user", userSchema);
module.exports = UserModel;

@ -1,43 +1,25 @@
{
"name": "favor",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"node-sass": "^7.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.2",
"react-scripts": "^2.1.3",
"sass": "^1.55.0",
"save": "^2.9.0",
"tachyons": "^4.12.0",
"web-vitals": "^2.1.4"
},
"name": "projet-favor-complet",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"start": "nodemon server.js"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.1.3",
"bcrypt": "^5.1.0",
"body-parser": "^1.20.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"jsonwebtoken": "^8.5.1",
"mongoose": "^6.6.6",
"nodemon": "^2.0.20",
"validator": "^13.7.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>Favor</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

@ -0,0 +1,22 @@
const router = require('express').Router();
const authController = require('../controllers/auth.controller.js');
const userController = require('../controllers/user.controller.js');
//auth
//controlleur d'authentification
router.post('/register', authController.signUp);
router.post('/login', authController.signIn);
//retirer le token (cookie)
router.get('/logout', authController.logout);
// user
router.get('/', userController.getAllUsers);
router.get('/:id', userController.userInfo);
//put pour faire des updates
router.put('/:id', userController.updateUser);
router.delete('/:id', userController.deleteUser);
router.patch('/follow/:id', userController.follow);
router.patch('/unfollow/:id', userController.unfollow);
module.exports = router;

@ -0,0 +1,47 @@
//Utilisation de express/dotenv
const express = require('express');
const userRoutes = require('./routes/user.routes');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
require('dotenv').config({path: './config/.env'});
require('./config/db.js');
const {checkUser, requireAuth} = require('./middleware/auth.middleware');
const cors = require('cors');
const app = express();
//autorise tout le monde à faire des requetes
//app.use(cors());
//autorise seulement les client à effectuer des requetes
const corsOptions = {
origin: process.env.CLIENT_URL,
credentials: true,
'allowedHeaders': ['sessionId', 'Content-Type'],
'exposedHeaders': ['sessionId'],
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}
app.use(cors(corsOptions));
//prend la requete et la rend au bon format
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//permet de lire les cookies
app.use(cookieParser());
//jwt
app.get('*', checkUser);
app.get('/jwtid', requireAuth, (req, res) => {
res.status(200).send(res.locals.user._id);
});
//routes
//toutes les routes qui vont avoir un lien avec le user
app.use('/api/user', userRoutes);
//server
//process.env.PORT (récupérer la variable PORT)
app.listen(process.env.PORT, () => {
console.log(`Listening on port ${process.env.PORT}`);
})

@ -1,27 +0,0 @@
//import logo from './logo.svg';
import React from 'react';
import 'tachyons';
import Connexion from './pages/Connexion';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from './pages/Home';
import Tendances from './pages/Tendances';
import Decouvrir from './pages/Decouvrir';
import Inscription from './pages/Inscription';
import "./styles/index.scss"
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Connexion/>} />
<Route path="/inscription" element={<Inscription/>} />
<Route path="/home" element={<Home/>} />
<Route path="/tendances" element={<Tendances/>} />
<Route path="/decouvrir" element={<Decouvrir/>} />
<Route path="*" element={<Connexion/>} />
</Routes>
</BrowserRouter>
);
}
export default App;

@ -1,8 +0,0 @@
import { render, screen } from '@testing-library/react';
import App from './components/App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

@ -1,3 +0,0 @@
<svg id="Flat" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<path d="M128,20A108,108,0,1,0,236,128,108.12186,108.12186,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09562,84.09562,0,0,1,128,212Zm16-84a16,16,0,1,1-16-16A16.01833,16.01833,0,0,1,144,128Zm48,0a16,16,0,1,1-16-16A16.01833,16.01833,0,0,1,192,128Zm-96,0a16,16,0,1,1-16-16A16.01833,16.01833,0,0,1,96,128Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

@ -1,63 +0,0 @@
import React from "react";
import { NavLink } from "react-router-dom";
import PP from "../assets/img/unknown.png";
const Navbar = () => {
return (
<header>
<nav>
<ul className="partie-gauche-nav">
<li className="logo">
<img src=''alt='Logo'/>
</li>
</ul>
<ul>
<li>
<NavLink to="/Decouvrir" className={((nav) => (nav.isActive ? "nav-active b nav-active-tendances-decouvrir" : "b"))}>
<span>Découvrir</span>
</NavLink>
</li>
<li>
<NavLink to="/Home" className={((nav) => (nav.isActive ? "nav-active b nav-active-menu" : "b"))}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" className="svg-home">
<path stroke="black" fill='black' d="M256 73.825a182.18 182.18 0 0 0-182.18 182.18c0 100.617 81.567 182.17 182.18 182.17a182.175 182.175 0 1 0 0-364.35zm76.636 161.579h-12.037v91.503a18.908 18.908 0 0 1-18.896 18.904h-26.78v-53.56a6.299 6.299 0 0 0-6.297-6.294H232.4a6.3 6.3 0 0 0-6.302 6.294v53.56h-26.771a18.91 18.91 0 0 1-18.906-18.904v-91.503h-11.97a7.879 7.879 0 0 1-5.071-13.905l82.055-69.039a7.89 7.89 0 0 1 10.142 0l81.479 68.547a7.88 7.88 0 0 1-4.421 14.396z" data-name="Home"/>
</svg>
</NavLink>
</li>
<li>
<NavLink to="/Tendances" className={((nav) => (nav.isActive ? "nav-active b nav-active-tendances-decouvrir" : "b"))}>
<span>Tendances</span>
</NavLink>
</li>
</ul>
<ul className="partie-droit-nav">
<li >
<NavLink to="/Tendances" className='b'>
<span>pseudo</span>
</NavLink>
</li>
<li>
<NavLink to="/Tendances" className='b'>
<img src={PP} alt='Logo' className="img-profile"/>
</NavLink>
</li>
<li>
<NavLink to="/Tendances" className='b'>
<svg xmlns="http://www.w3.org/2000/svg" className="svg-param" viewBox="0 0 256 256">
<path d="M128,24A104,104,0,1,0,232,128,104.11791,104.11791,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.09957,88.09957,0,0,1,128,216Zm12-88a12,12,0,1,1-12-12A12.01375,12.01375,0,0,1,140,128Zm48,0a12,12,0,1,1-12-12A12.01375,12.01375,0,0,1,188,128Zm-96,0a12,12,0,1,1-12-12A12.01375,12.01375,0,0,1,92,128Z"/>
</svg>
</NavLink>
</li>
</ul>
</nav>
</header>
);
}
export default Navbar;

@ -1,51 +0,0 @@
import React, { Component, useEffect, useState } from "react";
import ReactDOM from "react-dom";
import PP from "../assets/img/photoProfileTest.png";
import coeurs from "../assets/img/coeurs.png";
import commentaire from "../assets/img/commentaire.png";
import "../styles/components/_poste.scss";
const Poste = () => {
return (
<div id="cadrePoste">
<div id="hautPoste">
<div id="cadreInfoPoste">
<img id="PProfile" src={PP} alt="photo de profile"/>
<h6 id="NomProfile">Lena 1er</h6>
</div>
<div>6 jours</div>
</div>
<div id="contenuePoste">
/*https://my.linkpreview.net/*/
{linkpreview("https://www.youtube.com")}
</div>
<div id="basPoste">
<div id="like">
<img src={coeurs}/>
<div>10k</div>
</div>
<div id="commentaire">
<img src={commentaire}/>
<div>10k</div>
</div>
</div>
</div>
);
}
function linkpreview(link){
const [preview, setPreview] = useState('');
var key = '89aa1d8dffb8b79473be782f14a2d53b';
link = 'http://api.linkpreview.net/?key='+key+'&q' + link;
console.log(link);
useEffect(() => {
fetch(link).then(res => res.json()).then(setPreview)
}, []);
return <div>{JSON.stringify(preview)}</div>;
}
export default Poste;

@ -1,34 +0,0 @@
import 'tachyons';
import React from 'react';
import '../styles/components/_connexion.scss';
import { NavLink } from "react-router-dom";
//import App from '../App';
function Connexion(){
return(
<div className='formulaire'>
<div className='cadre'>
<h1>Connexion</h1>
<form>
<div className='inputbox'>
<input type="text" required="required"/>
<span>email</span>
</div>
<div class="inputbox">
<input type="password" required="required"/>
<span>mot de passe</span>
</div>
<input type="submit" value="connexion"/>
<NavLink to="/Inscription" className='b'>
<button id="buttonTEL">Inscription</button>
</NavLink>
</form>
<p className=''>Mot de passe oublié?</p>
</div>
</div>
);
}
export default Connexion;

@ -1,12 +0,0 @@
import React from 'react';
import Navbar from '../components/Navbar';
const Decouvrir = () => {
return (
<div>
<Navbar/>
</div>
);
};
export default Decouvrir;

@ -1,14 +0,0 @@
import React from 'react';
import Navbar from '../components/Navbar';
import Poste from '../components/Poste';
const Home = () => {
return (
<div>
<Navbar/>
<Poste/>
</div>
);
};
export default Home;

@ -1,10 +0,0 @@
import React from 'react';
const Inscription = () => {
return (
<div>
</div>
);
};
export default Inscription;

@ -1,12 +0,0 @@
import React from 'react';
import Navbar from '../components/Navbar';
const Tendances = () => {
return (
<div>
<Navbar/>
</div>
);
};
export default Tendances;

@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@ -1,69 +0,0 @@
@import './../index.scss';
.formulaire {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.cadre {
position: relative;
padding: 50px 50px;
border-radius: 10px;
background-color: $color-1;
h1 {
letter-spacing: 5px;
margin-bottom: 60px;
font-weight: bold;
padding-left: 10px;
}
.inputbox {
position: relative;
width: 300px;
height: 50px;
margin-bottom: 25px;
input {
width: 100%;
border: 2px solid #000;
outline: none;
background-color: $color-3;
padding: 10px;
border-radius: 10px;
font-size: 1.2em;
}
span {
position: absolute;
top: 14px;
left: 20px;
font-size: 1em;
transition: 0.3s;
font-family: sans-serif;
}
}
}
.span_date{
margin-left: 7px;
font-size: 1em;
font-family: sans-serif;
}
.cadre .inputbox input:focus ~ span,
.cadre .inputbox input:valid ~ span {
transform: translateX(-13px) translateY(-35px);
font-size: 1em;
}
input[type="submit"], #buttonTEL{
border: none;
border-radius: 5px;
border: 2px solid #000;
background-color: $color-3;
margin: 10px 0px 0px 25%;
padding: 20px 10% 20px 10%;
}
input[type="submit"]:hover, #buttonTEL:hover{
background-color: $color-4;
}

@ -1,105 +0,0 @@
header {
height: 50px;
background-color: $color-2;
top: 0;
left: 0;
right: 0;
text-transform: uppercase;
color: #b9b9b9;
position: fixed;
}
nav{
display: flex;
align-items: center;
justify-content: space-between;
}
.logo{
//margin-right: 250px;
}
.partie-droit-nav,.partie-gauche-nav{
width: 20%;
}
.svg-home{
height: 45px;
width: 45px;
}
.svg-param{
height: 42px;
width: 42px;
}
ul{
display: flex;
li{
list-style-type: none;
padding-left: 1rem;
align-self: center;
}
.nav-active-menu {
padding-top: 50px;
}
.nav-active-tendances-decouvrir {
padding-bottom: 0.75rem;
}
.nav-active {
position: relative;
&::after {
content: "";
height: 4px;
background: violet;
position: absolute;
border-radius: 10px;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
-webkit-animation: anim 0.3s ease forwards;
animation: anim 0.6s ease forwards;
@-webkit-keyframes anim {
to {
width: 100%;
}
}
@keyframes anim {
to {
width: 100%;
}
}
}
}
}
.img-profile{
height: 35px;
width: 35px;
border-radius: 20px;
}
.b{
text-decoration: none;
cursor: pointer;
}
.n{
height: 0.95rem;
width: 0.95rem;
padding-top: 0.15rem;
overflow: hidden;
fill: #b9b9b9;
}

@ -1,49 +0,0 @@
#cadrePoste{
background: white;
border: 2px solid;
border-radius: 5px;
border-color: grey;
width: 40%;
margin-left: auto;
margin-right: auto;
}
#hautPoste{
display: flex;
align-items:center;
justify-content: space-between;
margin-right: 15px;
}
#cadreInfoPoste{
display: flex;
align-items:center;
}
#PProfile{
margin: 10px 15px 0px 20px;
width: 40px;
height:40px;
border-radius: 20px;
border: 2px solid #555;
}
#NomProfile{
font-family: arial;
font-size: 18px;
}
/*bas poste*/
#basPoste{
display: flex;
align-items:center;
justify-content: space-between;
margin-left: 10px;
margin-right: 10px;
}
#like, #commentaire{
display: flex;
align-items:center;
}

@ -1,2 +0,0 @@
@import "./settings";
@import "./components/navbar";

@ -0,0 +1,44 @@
module.exports.signUpErrors = (err) => {
let errors = { pseudo: "", email: "", password: "" };
if (err.message.includes("pseudo"))
errors.pseudo = "Pseudo incorrect ou déjà pris";
if (err.message.includes("email"))
errors.email = "Email incorrect";
if (err.message.includes("password"))
errors.password = "Le mot de passe doit faire 6 caractères minimum";
if (err.code === 11000 && Object.keys(err.keyValue)[0].includes("pseudo"))
errors.pseudo = "Ce pseudo est déjà pris";
if (err.code === 11000 && Object.keys(err.keyValue)[0].includes("email"))
errors.email = "Cet email est déjà enregistré";
return errors;
};
module.exports.signInErrors = (err) => {
let errors = { email: '', password: ''}
if (err.message.includes("email"))
errors.email = "Email inconnu";
if (err.message.includes('password'))
errors.password = "Le mot de passe ne correspond pas"
return errors;
}
module.exports.uploadErrors = (err) => {
let errors = { format: '', maxSize: ""};
if (err.message.includes('invalid file'))
errors.format = "Format incompatabile";
if (err.message.includes('max size'))
errors.maxSize = "Le fichier dépasse 500ko";
return errors
}
Loading…
Cancel
Save