diff --git a/backend/app.js b/backend/app.js index 2af6a3aed0588e3eb31d70b70ed5abad84987e35..87b275e516f879b36d6496f7bb8456d8b2788756 100644 --- a/backend/app.js +++ b/backend/app.js @@ -4,7 +4,6 @@ var path = require('path'); var logger = require('morgan'); var passport = require('passport'); const mongoose = require('mongoose'); -var usersRouter = require('./routes/users'); var authRouter = require('./routes/auth'); var app = express(); @@ -30,7 +29,6 @@ var env = process.env.NODE_ENV || 'dev'; if (env == 'production') { app.use("/", express.static(path.join(path.dirname(__dirname), '/frontend/build'))) } -app.use('/api/', usersRouter); app.use('/api/', authRouter); // catch 404 and forward to error handler diff --git a/backend/models/user.js b/backend/models/user.js index 4b9987921ded8b955ce20ac400cc97c434f15562..ad6965bed280c486fc2144df98ba28d328591f53 100644 --- a/backend/models/user.js +++ b/backend/models/user.js @@ -44,6 +44,7 @@ const UserSchema = new mongoose.Schema({ type: Number, unique: true, required: true, + unique: true, minlength: 8, maxlength: 8, select: true, diff --git a/backend/routes/auth.js b/backend/routes/auth.js index a5f4e782ecea3aa76241f4f10a351e6a5f310dcf..3a40dbfb80e9b0d26ff02e6aa08537cc1b7431e5 100644 --- a/backend/routes/auth.js +++ b/backend/routes/auth.js @@ -39,7 +39,7 @@ router.post('/login', async (req, res) => { // return if there was no user with this username found in the database if (!user) { - errors.message = "No Account Found"; + errors.message = "Aucun compte a été trouvé."; return res.status(400).json(errors); } @@ -141,4 +141,24 @@ router.post('/me/update', passport.authenticate('jwt', {session: false}), async res.status(200).json(); }); +router.post('/pay_adhesion', passport.authenticate('jwt', {session: false}), async function(req, res, next) { + const student_number = req.body.student_number; + + if (!student_number) + return res.status(400); + + const dbUser = await User.findOne({student_number: req.body.student_number}); + + + if (student_number) + dbUser.date_subscription = new Date(); + + try { + await dbUser.save(); + } catch (e) { + return res.status(400).json(e); + } + res.status(200).json(); +}); + module.exports = router; diff --git a/backend/routes/users.js b/backend/routes/users.js deleted file mode 100644 index 40d6752aaa4901a41bd4aca34d18de3c19db1cd3..0000000000000000000000000000000000000000 --- a/backend/routes/users.js +++ /dev/null @@ -1,27 +0,0 @@ -var express = require('express'); -var router = express.Router(); -const passport = require('passport'); -const User = require('../models/user'); - -router.get('/most-liked', async function(req, res, next) { - - // handle authentication manually, as we want the API to work in both cases, - // but to return 'liked' property if logged in - passport.authenticate('jwt', async function(err, user, info) { - var match = {} - if (user) { - match = {liker: user.id}; - } - const users = await User.find( - ).populate({path:'liked', match: match}).populate({path:'likes'}).sort({'likes': -1}); - res.status(200).json(users); - })(req, res, next); - -}); - -router.get('/user/:username', async function(req, res, next) { - const user = await User.findOne({username: req.params.username}).populate('likes'); - res.status(200).json(user); -}); - -module.exports = router; diff --git a/backend/tests/test.js b/backend/tests/test.js index d9e27aa297220902fb13d5ec507512dc6338291a..46cdbb10cbc529fb954f65d7bfacd79b1f413d8a 100644 --- a/backend/tests/test.js +++ b/backend/tests/test.js @@ -46,23 +46,6 @@ describe('app', function() { }) - describe('GET /most-liked', function() { - this.timeout(3000); - - before(async function () { - res = await baseUrl.get('/api/most-liked') - .set('Accept', 'application/json') - .set('Content-Type', 'application/json') - .send(); - }); - - it('respond with an array of most liked users', function(done) { - expect(res.status).to.equal(200); - expect(res.body).to.be.an('array'); - done(); - }); - }); - describe('POST /login', function() { this.timeout(3000); diff --git a/frontend/src/App.js b/frontend/src/App.js index 89532ce2ae722bcb378f9206b62c3c1192c05c10..3c8cc126148fe47f08be28ded8acba7f33c42209 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import './App.css'; import {connect} from 'react-redux'; import {BrowserRouter as Router, Route, Link, Redirect} from "react-router-dom"; -import Users from './containers/Users.container'; import SignUp from './containers/SignUp.container'; import Login from './containers/Login.container'; import Privacy from './containers/Privacy.container' diff --git a/frontend/src/actions/Login.actions.js b/frontend/src/actions/Login.actions.js index 23ba633a85d2cd2c2926204984ed57059781bca3..7f2a953122e4206e14a3c3bb8b8cea41252f2aea 100644 --- a/frontend/src/actions/Login.actions.js +++ b/frontend/src/actions/Login.actions.js @@ -54,7 +54,8 @@ export const login = (loginData, ownProps) => { if(response.ok){ response.json().then(data => { userService.setToken(data.token); - dispatch(fetchUserData()); + let user = dispatch(fetchUserData()); + //dispatch(user); ownProps.history.push('/'); @@ -96,4 +97,3 @@ export const reinitializeState = () => { type:'REINITIALIZE_STATE' } } - diff --git a/frontend/src/actions/Login.actions.js.BASE b/frontend/src/actions/Login.actions.js.BASE new file mode 100644 index 0000000000000000000000000000000000000000..44c4a25ee7fdeaa0f5caade6af2836edb0cf0ca6 --- /dev/null +++ b/frontend/src/actions/Login.actions.js.BASE @@ -0,0 +1,92 @@ +import { userService } from "../services/authentication.service"; +import {fetchUserData} from "./Profile.actions"; + +export const getAuth = () => { + return { + type:'GET_AUTH' + } +} + +export const logoutSuccess = () => { + return { + type:'LOGOUT_SUCCESS' + } +} + +export const loginSuccessWaitForPayment = () => { + return { + type:'LOGIN_SUCCESS_WAIT_PAYMENT' + } +} + +export const loginSuccesPaymentDone = () => { + return { + type:'LOGIN_SUCCESS_PAYMENT_DONE' + } +} + +export const loginFailed = (message) => { + return { + type:'LOGIN_FAILED', + message: message + } +} + +export const loginRequest = () => { + return { + type:'LOGIN_REQUEST' + } +} + +export const login = (loginData, ownProps) => { + return async (dispatch) => { + dispatch(loginRequest()); + + const response = await fetch( "/api/login", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(loginData), + }) + + if(response.ok){ + response.json().then(data => { + userService.setToken(data.token); + dispatch(fetchUserData()); + ownProps.history.push('/'); + // TODO: do another request to know if user paid adhesion + var paid=true; + if(paid){ + userService.setAdhesion(true); + dispatch(loginSuccesPaymentDone(data)); + } else { + userService.setToken(false); + dispatch(loginSuccessWaitForPayment(data)); + } + }).catch(err => dispatch(loginFailed(err))); + } + else{ + response.json().then(error => { + dispatch(loginFailed(error)); + }).catch(err => dispatch(loginFailed(err))); + } + + return response; + } +} + +export const logout = () => { + return (dispatch) => { + userService.logout(); + dispatch(logoutSuccess()); + } +} + +export const reinitializeState = () => { + return { + type:'REINITIALIZE_STATE' + } +} + diff --git a/frontend/src/actions/Login.actions.js.LOCAL b/frontend/src/actions/Login.actions.js.LOCAL new file mode 100644 index 0000000000000000000000000000000000000000..23ba633a85d2cd2c2926204984ed57059781bca3 --- /dev/null +++ b/frontend/src/actions/Login.actions.js.LOCAL @@ -0,0 +1,99 @@ +import { userService } from "../services/authentication.service"; +import {fetchUserData} from "./Profile.actions"; + +export const getAuth = () => { + return { + type:'GET_AUTH' + } +} + +export const logoutSuccess = () => { + return { + type:'LOGOUT_SUCCESS' + } +} + +export const loginSuccessWaitForPayment = () => { + return { + type:'LOGIN_SUCCESS_WAIT_PAYMENT' + } +} + +export const loginSuccesPaymentDone = () => { + return { + type:'LOGIN_SUCCESS_PAYMENT_DONE' + } +} + +export const loginFailed = (message) => { + return { + type:'LOGIN_FAILED', + message: message + } +} + +export const loginRequest = () => { + return { + type:'LOGIN_REQUEST' + } +} + +export const login = (loginData, ownProps) => { + return async (dispatch) => { + dispatch(loginRequest()); + + const response = await fetch( "/api/login", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(loginData), + }) + + if(response.ok){ + response.json().then(data => { + userService.setToken(data.token); + dispatch(fetchUserData()); + ownProps.history.push('/'); + + + // TODO: do another request to know if user paid adhesion + // make request to get user data + + + var paid=true; + + + if(paid){ + userService.setAdhesion(true); + dispatch(loginSuccesPaymentDone(data)); + } else { + userService.setToken(false); + dispatch(loginSuccessWaitForPayment(data)); + } + }).catch(err => dispatch(loginFailed(err))); + } + else{ + response.json().then(error => { + dispatch(loginFailed(error)); + }).catch(err => dispatch(loginFailed(err))); + } + + return response; + } +} + +export const logout = () => { + return (dispatch) => { + userService.logout(); + dispatch(logoutSuccess()); + } +} + +export const reinitializeState = () => { + return { + type:'REINITIALIZE_STATE' + } +} + diff --git a/frontend/src/actions/Login.actions.js.REMOTE b/frontend/src/actions/Login.actions.js.REMOTE new file mode 100644 index 0000000000000000000000000000000000000000..967ae30ba2cfd66ec78a919aa7905df612459c7b --- /dev/null +++ b/frontend/src/actions/Login.actions.js.REMOTE @@ -0,0 +1,93 @@ +import { userService } from "../services/authentication.service"; +import {fetchUserData} from "./Profile.actions"; + +export const getAuth = () => { + return { + type:'GET_AUTH' + } +} + +export const logoutSuccess = () => { + return { + type:'LOGOUT_SUCCESS' + } +} + +export const loginSuccessWaitForPayment = () => { + return { + type:'LOGIN_SUCCESS_WAIT_PAYMENT' + } +} + +export const loginSuccesPaymentDone = () => { + return { + type:'LOGIN_SUCCESS_PAYMENT_DONE' + } +} + +export const loginFailed = (message) => { + return { + type:'LOGIN_FAILED', + message: message + } +} + +export const loginRequest = () => { + return { + type:'LOGIN_REQUEST' + } +} + +export const login = (loginData, ownProps) => { + return async (dispatch) => { + dispatch(loginRequest()); + + const response = await fetch( "/api/login", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(loginData), + }) + + if(response.ok){ + response.json().then(data => { + userService.setToken(data.token); + let user = dispatch(fetchUserData()); + //dispatch(user); + ownProps.history.push('/'); + // TODO: do another request to know if user paid adhesion + console.log(user) + var paid=true; + if(paid){ + userService.setAdhesion(true); + dispatch(loginSuccesPaymentDone(data)); + } else { + userService.setToken(false); + dispatch(loginSuccessWaitForPayment(data)); + } + }).catch(err => dispatch(loginFailed(err))); + } + else{ + response.json().then(error => { + dispatch(loginFailed(error)); + }).catch(err => dispatch(loginFailed(err))); + } + + return response; + } +} + +export const logout = () => { + return (dispatch) => { + userService.logout(); + dispatch(logoutSuccess()); + } +} + +export const reinitializeState = () => { + return { + type:'REINITIALIZE_STATE' + } +} diff --git a/frontend/src/actions/Users.actions.js b/frontend/src/actions/Users.actions.js deleted file mode 100644 index be9177ab33b7aa45d2733118cbc928ecb228a989..0000000000000000000000000000000000000000 --- a/frontend/src/actions/Users.actions.js +++ /dev/null @@ -1,50 +0,0 @@ -import { userService } from "../services/authentication.service"; - -export const fetchUsersSuccess = (users) => { - return { - type: 'FETCH_USERS_SUCCESS', - users: users, - receivedAt: Date.now - } -} - -export const fetchUsersFailed = (error) => { - return { - type:'FETCH_USERS_FAILED', - error - } -} - -export const fetchUsersRequest = () => { - return { - type:'FETCH_USERS_REQUEST' - } -} - -export const fetchUsers = () => { - return async (dispatch) => { - dispatch(fetchUsersRequest()); - - const response = await fetch( "/api/most-liked", { - headers: { - 'Authorization': userService.getToken() - } - }); - - if(response.ok){ - response.json().then(data => { - data.sort(function(a, b){ - return b.likes - a.likes; - }); - dispatch(fetchUsersSuccess(data)); - }).catch(err => dispatch(fetchUsersFailed(err))); - } - else{ - response.json().then(error => { - dispatch(fetchUsersFailed(error)); - }).catch(err => dispatch(fetchUsersFailed(err))); - } - - return response; - } -} diff --git a/frontend/src/components/User.component.js b/frontend/src/components/User.component.js deleted file mode 100644 index 5e1d9db14cdaa9fe3dfc5356b99470ddbd3e0bc4..0000000000000000000000000000000000000000 --- a/frontend/src/components/User.component.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -export class User extends React.Component { - render() { - return ( - <tr> - <td>{this.props.user.username}</td> - </tr> - ); - } -} diff --git a/frontend/src/containers/Users.container.js b/frontend/src/containers/Users.container.js deleted file mode 100644 index 207561fab9a928f2513a03840c79c303b920596a..0000000000000000000000000000000000000000 --- a/frontend/src/containers/Users.container.js +++ /dev/null @@ -1,69 +0,0 @@ -import { connect } from 'react-redux'; -import React from 'react'; -import { withRouter } from 'react-router-dom' -import * as userActions from '../actions/Users.actions'; -import { User } from '../components/User.component'; -import { Card, Table, Nav } from 'react-bootstrap'; -import { Link} from "react-router-dom"; - -export class Users extends React.Component { - // constructor(props){ - // super(props); - // } - - componentDidMount(){ - this.props.fetchUsers(); - } - - render() { - return ( - <div> - <Card style={{ width: '90vw', margin: '0 auto', marginTop:'30px' }}> - <Card.Body> - <Card.Title>Utilisateurs</Card.Title> - <Table striped bordered hover> - <thead> - <tr> - <td>Nom d'utilisateur</td> - </tr> - </thead> - <tbody> - {this.props.state.users.map((value, index) => { - return <User key={index} likeUser={this.props.likeUser} unlikeUser={this.props.unlikeUser} user={value} appState={this.props.loginState} profileState={this.props.profileState}></User> - })} - </tbody> - </Table> - {this.props.state.error && <div>Une erreur est survenue pendant le chargement des utilisateurs.</div>} - {this.props.state.loading && <div>Chargement...</div>} - </Card.Body> - </Card> - <footer className="footer mt-auto py-3"> - <div className="container" style={{ textAlign : "center"}}> - <Nav.Link as={Link} to="/privacy/"> - Politique de confidentialité - </Nav.Link> - </div> - </footer> - </div> - ); - } -} - -// map state from store to props -const mapStateToProps = (state) => { - return { - state: state.users, - loginState: state.login, - profileState: state.profile, - } -} - -// map actions to props -const mapDispatchToProps = (dispatch) => { - return { - fetchUsers: () => dispatch(userActions.fetchUsers()), - } -} - - -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Users)) diff --git a/frontend/src/reducers/Users.reducer.js b/frontend/src/reducers/Users.reducer.js deleted file mode 100644 index 68ab73c1b6874c896b7a2f115cd26298cb159e92..0000000000000000000000000000000000000000 --- a/frontend/src/reducers/Users.reducer.js +++ /dev/null @@ -1,20 +0,0 @@ -const INITIAL_STATE = { - users: [], - loading: true, - error: false -} - -const usersReducer = (currentState = INITIAL_STATE, action) => { - switch (action.type) { - case 'FETCH_USERS_SUCCESS': - return {...currentState, loading: false, users: action.users, error: false}; - case 'FETCH_USERS_REQUEST': - return {...currentState, loading: true, error: false}; - case 'FETCH_USERS_FAILED': - return {...currentState, error: true, loading: false}; - default: - return currentState; - } -} - -export default usersReducer; \ No newline at end of file diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js index b037e3ac4ac41f4e66f7ab65d776ea645729ce77..c9bd461735c19802d90a1764c7dfb1af201694db 100644 --- a/frontend/src/reducers/index.js +++ b/frontend/src/reducers/index.js @@ -1,14 +1,12 @@ import { routerReducer } from 'react-router-redux'; import { combineReducers } from 'redux'; import appReducer from './App.reducer'; -import usersReducer from './Users.reducer'; import signupReducer from './SignUp.reducer'; import loginReducer from './Login.reducer'; import profileReducer from './Profile.reducer'; export default combineReducers({ app:appReducer, - users:usersReducer, signup:signupReducer, login:loginReducer, profile:profileReducer,