From c0b554ff35d1b4c27225a9a49f56ac2a5a86498a Mon Sep 17 00:00:00 2001 From: Shohei Date: Sun, 17 Jun 2018 04:06:15 +0000 Subject: [PATCH 1/8] Worked on backend code to delete user --- .gitignore | 3 ++- routes/users/users.js | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 309f129f..85212dc8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ src/**/*.css build/* npm-debug.log -TODO \ No newline at end of file +TODO +mongo/ \ No newline at end of file diff --git a/routes/users/users.js b/routes/users/users.js index a48ec942..54e36131 100644 --- a/routes/users/users.js +++ b/routes/users/users.js @@ -91,15 +91,20 @@ router.route('/:user_id') //delete method for removing a user from our database .delete(function(req, res) { - User.findById(req.user._id) - .exec(function (err, user) { - if (!user._id.equals(req.user._id)) return res.json({ message: 'Users do not match'}); - //selects the user by its ID, then removes it. - User.remove({ _id: req.params.user_id }, function(err, user) { - if (err) { res.send(err); } - return res.json({ message: 'User has been deleted' }) - }) - }) + User.findById(req.params.user_id) + .exec(function (err, user) { + if (err) return res.send(err); + if (user._id === req.user._id) { + // user to be deleted is owned by the logged in user + user.remove({ _id: req.params.user_id }, function(err, user) { + if (err) { res.send(err); } + }); + return res.redirect('/'); + } else { + // user to be deleted is not owned by the logged in user + return res.send('Cannot delete account not owned by the user'); + } + }) }); router.route('/contact/:user_id') From 287fbf1ba9a3319a65fefdb8a1a05c7908dad0d3 Mon Sep 17 00:00:00 2001 From: Shohei Shibata Date: Mon, 18 Jun 2018 05:56:42 +0200 Subject: [PATCH 2/8] Delete user button added --- src/components/molecules/UserInfo.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/molecules/UserInfo.js b/src/components/molecules/UserInfo.js index dcfc9eb9..248afb6b 100644 --- a/src/components/molecules/UserInfo.js +++ b/src/components/molecules/UserInfo.js @@ -102,7 +102,11 @@ class UserInfo extends Component {
{(this.props.user && user._id === this.props.user._id) ? - (
+ ) : ( ) diff --git a/src/components/molecules/UserInfo.js b/src/components/molecules/UserInfo.js index 248afb6b..f6f7e82d 100644 --- a/src/components/molecules/UserInfo.js +++ b/src/components/molecules/UserInfo.js @@ -4,6 +4,8 @@ ------------------------*/ import React, { Component } from 'react'; +import { Modal, ModalHeader, ModalBody, Form, FormGroup, Input } from "reactstrap"; + import Button from '../atoms/Button.js'; import Loader from "../atoms/Loader.js"; import defaultAvatar from "../../images/default-avatar.png"; @@ -14,7 +16,8 @@ class UserInfo extends Component { super(props); this.state = { user: null, - projects: null + projects: null, + showModal: false }; } componentDidMount() { @@ -46,6 +49,12 @@ class UserInfo extends Component { handleClick = (e) => { this.props.history.push('/project/view/' + e.target.id); } + toggleModal = () => { + console.log('toggle modal', this.state.showModal); + this.setState({ + showModal: !this.state.showModal + }); + } renderInfo = (user, projects) => { if (user) { return ( @@ -104,11 +113,20 @@ class UserInfo extends Component { {(this.props.user && user._id === this.props.user._id) ? (
) : ( + ) : ( + + diff --git a/src/js/apiCalls.js b/src/js/apiCalls.js index bfa2d532..eb04827f 100644 --- a/src/js/apiCalls.js +++ b/src/js/apiCalls.js @@ -10,6 +10,7 @@ const apiCall = { // Retrieve all projects from server getAllProjects(next) { // get projects from api + console.log('get all projects url', apiUrl + '/api/projects'); axios.get(apiUrl + '/api/projects') .then(res => { next({data: res.data}); diff --git a/src/js/fakeApi.js b/src/js/fakeApi.js new file mode 100644 index 00000000..905b1c17 --- /dev/null +++ b/src/js/fakeApi.js @@ -0,0 +1,53 @@ +const fakeData = { + user: { + _id: "12345", + username: "fakeUser", + skillset: ["One", "Two", "Three"], + avatar: "https://picsum.photos/50" + }, + projects: [{"_id":"5a65fd8a3d77f50004decf51","repoUrl":"http://www.ideaswatch.com/startup-idea/fake-at-party-app","status":"I have the idea, but I haven't started coding it yet.","description":"This app creates background noises (e.g. traffic, loud music, people in a party chatting) when you are calling. This is useful when you're ex is calling, so you can pretend you're busy having fun!","owner":"5a6247110173f1000448b79d","title":"Noisr","__v":8,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["NA"],"stack":["Java","Swift"],"categories":["Mobile App"]},{"_id":"5a66116211a5c72408a19281","repoUrl":"NA","status":"It's just an idea","description":"Find coworkers in your area to commute with.","owner":"5a6247110173f1000448b79d","title":"CommuteWithMe","__v":12,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a7b8c2b128e880004cb2dbf","status":"following"}],"img":[],"stack":["React Native"],"categories":["Mobile App"]},{"_id":"5a7b8d82128e880004cb2dc0","repoUrl":"https://github.com/chingu-coders/Voyage2-Turtles-02","status":"Currently complete but we are currently working on V2 which would include a faster DevTab and more features. (Created by Dan Nguyen, Jeff Bothe, Tyler Del Rosario)\nDevTab is a Chingu Project","description":"An awesome new-tab extension designed for Developers","owner":"","title":"DevTab","__v":10,"users":[{"_id":"5a7b8c2b128e880004cb2dbf","status":"owner"}],"img":[],"stack":["HTML","CSS","JS","jQuery","jQuery UI"],"categories":["New-Tab Extension"]},{"_id":"5a7b8eb9128e880004cb2dc1","repoUrl":"https://github.com/chingu-voyage3/bears-06","status":"BearBnB is a completed Chingu Project :D(Created by Vannya, Stephan, Lee)\n ","description":"An open-source clone of AirBnB.","title":"BearBnB","__v":11,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["MERN Stack","Mongo","Express","ReactJS","Node"],"categories":["App Clone"]},{"_id":"5ad5b3a8cdc05a3a50119f28","repoUrl":"http://","status":"Stuck","description":"The most generic project ever","title":"Yet another project","__v":1,"users":[{"_id":"5a9a9139ab060929303bded4","status":"owner"},{"_id":"5af4874738973100045687d3","status":"following"}],"img":[],"stack":["Mern"],"categories":["Web app"]},{"_id":"5af4879838973100045687d4","repoUrl":"http","status":"begin","description":"ever project best","title":"bookface","__v":0,"users":[{"_id":"5af4874738973100045687d3","status":"owner"}],"img":[],"stack":[],"categories":["Web app"]},{"_id":"5a660fbb11a5c72408a1927f","repoUrl":"http://www.ideaswatch.com/startup-idea/rifflord","status":"Idea found on IdeasWatch - never started","description":"Find and connect with musicians around you and form your band. On RiffLord you can upload a sample of your music and browse through musicians living around your area.","title":"RiffLord","__v":2,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5b074a9f2a1ccc0004510e38","status":"following"}],"img":[],"stack":["TBD"],"categories":["Social Network"]},{"_id":"5a663627d1a0785a64e8b6e3","repoUrl":"http://github.com","status":"Just an idea. Looking for devs to build it!","description":"This is a social network for unsociable people. It will text you when someone you DON'T want to meet is nearby.","title":"UnSocial Network","__v":1,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["https://cdn.images.express.co.uk/img/dynamic/80/590x/Grumpy-Cat-on-bed-544409.jpg"],"stack":["HTML","CSS","JavaScript"],"categories":["Web App"]},{"_id":"5a660f1f11a5c72408a1927e","repoUrl":"https://bitbucket.org/AlexGherardelli/evergreen","status":"I got stuck because I could not figure out how to post things on behalf of users with Flask and the Twitter API. I would love to have a more expert developer helping me with this project!","description":"Evergreen is a social media management app that allows you to reschedule your best and most effective posts over and over again, to maximize engagement and exposure. For example, you can schedule a \"Happy New Year\" post and never worry ever again to post it again. Or you can resend the invitation to an event multiple times at different times, so that people in different time zones can see your post.","title":"Evergreen","__v":4,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["Flask (Python)","HTML","SCSS/SASS","JavaScript"],"categories":["Social media management"]},{"_id":"5a66109911a5c72408a19280","repoUrl":"https://bitbucket.org/AlexGherardelli/dickens","status":"I have the boilerplate, but I would like a team mate to develop it.","description":"I have read online that with the time people spend on social media, they could read 200 books a year. With this scary stat in mind, I thought it would be nice to build a browser extension that every time you connect to a social media like Facebook, it redirects you toward a short story that can be read in a few minutes. A more productive break indeed!","owner":"5a6247110173f1000448b79d","title":"Dickens","__v":14,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5acadeeffcadd708d6d029d6","status":"following"}],"img":["https://i2-prod.mirror.co.uk/incoming/article5418983.ece/ALTERNATES/s615/Charles-Dickens.jpg"],"stack":[],"categories":["Browser Extension"]}] +}; + +const fakeApi = { + // Retrieve all projects from server + getAllProjects(next) { + // get projects from api + console.log('FAKE get all projects url'); + next({data: fakeData.projects}); + }, + // Retrieve one project by ID + getProjectById(projects, projectId, next) { + console.log('FAKE get project by ID'); + next({data: fakeData.projects[0]}); + }, + // Get logged in user data from api and assign it to state + getCurrentUser(next) { + console.log('FAKE get currentUser'); + next({data: fakeData.user}); + }, + // get user data from api + getUserById(id, next) { + console.log('FAKE get user by ID'); + next({data: fakeData.user}); + }, + + // Updates user data + postUser(data, next) { + console.log('FAKE postUser'); + next({data: "FAKE postUser"}); + }, + + // creates new project or updates a project + postProject(data, next) { + console.log('FAKE postProject'); + next({data: "FAKE postProject"}); + }, + + // delete project + deleteProject(data, next) { + console.log('FAKE deleteProject'); + next({data: "FAKE deleteProject"}); + } +}; + +export default fakeApi; \ No newline at end of file diff --git a/src/js/fakeAuth.js b/src/js/fakeAuth.js new file mode 100644 index 00000000..8a03c7bd --- /dev/null +++ b/src/js/fakeAuth.js @@ -0,0 +1,11 @@ +const fakeAuth = { + user: { + _id: "12345", + username: "fakeUser", + skillset: ["One", "Two", "Three"], + avatar: "https://picsum.photos/50" + }, + projects: [{"_id":"5a65fd8a3d77f50004decf51","repoUrl":"http://www.ideaswatch.com/startup-idea/fake-at-party-app","status":"I have the idea, but I haven't started coding it yet.","description":"This app creates background noises (e.g. traffic, loud music, people in a party chatting) when you are calling. This is useful when you're ex is calling, so you can pretend you're busy having fun!","owner":"5a6247110173f1000448b79d","title":"Noisr","__v":8,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["NA"],"stack":["Java","Swift"],"categories":["Mobile App"]},{"_id":"5a66116211a5c72408a19281","repoUrl":"NA","status":"It's just an idea","description":"Find coworkers in your area to commute with.","owner":"5a6247110173f1000448b79d","title":"CommuteWithMe","__v":12,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a7b8c2b128e880004cb2dbf","status":"following"}],"img":[],"stack":["React Native"],"categories":["Mobile App"]},{"_id":"5a7b8d82128e880004cb2dc0","repoUrl":"https://github.com/chingu-coders/Voyage2-Turtles-02","status":"Currently complete but we are currently working on V2 which would include a faster DevTab and more features. (Created by Dan Nguyen, Jeff Bothe, Tyler Del Rosario)\nDevTab is a Chingu Project","description":"An awesome new-tab extension designed for Developers","owner":"","title":"DevTab","__v":10,"users":[{"_id":"5a7b8c2b128e880004cb2dbf","status":"owner"}],"img":[],"stack":["HTML","CSS","JS","jQuery","jQuery UI"],"categories":["New-Tab Extension"]},{"_id":"5a7b8eb9128e880004cb2dc1","repoUrl":"https://github.com/chingu-voyage3/bears-06","status":"BearBnB is a completed Chingu Project :D(Created by Vannya, Stephan, Lee)\n ","description":"An open-source clone of AirBnB.","title":"BearBnB","__v":11,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["MERN Stack","Mongo","Express","ReactJS","Node"],"categories":["App Clone"]},{"_id":"5ad5b3a8cdc05a3a50119f28","repoUrl":"http://","status":"Stuck","description":"The most generic project ever","title":"Yet another project","__v":1,"users":[{"_id":"5a9a9139ab060929303bded4","status":"owner"},{"_id":"5af4874738973100045687d3","status":"following"}],"img":[],"stack":["Mern"],"categories":["Web app"]},{"_id":"5af4879838973100045687d4","repoUrl":"http","status":"begin","description":"ever project best","title":"bookface","__v":0,"users":[{"_id":"5af4874738973100045687d3","status":"owner"}],"img":[],"stack":[],"categories":["Web app"]},{"_id":"5a660fbb11a5c72408a1927f","repoUrl":"http://www.ideaswatch.com/startup-idea/rifflord","status":"Idea found on IdeasWatch - never started","description":"Find and connect with musicians around you and form your band. On RiffLord you can upload a sample of your music and browse through musicians living around your area.","title":"RiffLord","__v":2,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5b074a9f2a1ccc0004510e38","status":"following"}],"img":[],"stack":["TBD"],"categories":["Social Network"]},{"_id":"5a663627d1a0785a64e8b6e3","repoUrl":"http://github.com","status":"Just an idea. Looking for devs to build it!","description":"This is a social network for unsociable people. It will text you when someone you DON'T want to meet is nearby.","title":"UnSocial Network","__v":1,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["https://cdn.images.express.co.uk/img/dynamic/80/590x/Grumpy-Cat-on-bed-544409.jpg"],"stack":["HTML","CSS","JavaScript"],"categories":["Web App"]},{"_id":"5a660f1f11a5c72408a1927e","repoUrl":"https://bitbucket.org/AlexGherardelli/evergreen","status":"I got stuck because I could not figure out how to post things on behalf of users with Flask and the Twitter API. I would love to have a more expert developer helping me with this project!","description":"Evergreen is a social media management app that allows you to reschedule your best and most effective posts over and over again, to maximize engagement and exposure. For example, you can schedule a \"Happy New Year\" post and never worry ever again to post it again. Or you can resend the invitation to an event multiple times at different times, so that people in different time zones can see your post.","title":"Evergreen","__v":4,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["Flask (Python)","HTML","SCSS/SASS","JavaScript"],"categories":["Social media management"]},{"_id":"5a66109911a5c72408a19280","repoUrl":"https://bitbucket.org/AlexGherardelli/dickens","status":"I have the boilerplate, but I would like a team mate to develop it.","description":"I have read online that with the time people spend on social media, they could read 200 books a year. With this scary stat in mind, I thought it would be nice to build a browser extension that every time you connect to a social media like Facebook, it redirects you toward a short story that can be read in a few minutes. A more productive break indeed!","owner":"5a6247110173f1000448b79d","title":"Dickens","__v":14,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5acadeeffcadd708d6d029d6","status":"following"}],"img":["https://i2-prod.mirror.co.uk/incoming/article5418983.ece/ALTERNATES/s615/Charles-Dickens.jpg"],"stack":[],"categories":["Browser Extension"]}] +}; + +export default fakeAuth; \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index 53dcc065..6ffed9ad 100644 --- a/src/routes.js +++ b/src/routes.js @@ -9,6 +9,7 @@ import axios from 'axios'; // Import Javascript functions import getCookie from './js/getCookie'; import apiCall from './js/apiCalls'; +import fakeApi from './js/fakeApi'; // Actions import { setUser, logoutUser } from './actions/users.js'; @@ -36,9 +37,15 @@ import Dashboard from './components/molecules/Dashboard'; // Loads environment variables with dotenv require('dotenv').load(); +let api = apiCall; +if (process.env.REACT_APP_FAKE) { + console.log("***FAKE MODE***"); + api = fakeApi; +} + // Declare App component class App extends Component { - constructor(props) { + /*constructor(props) { super(props); // url is REACT_APP_APPURL if set, otherwise it's window.location.origin @@ -50,7 +57,7 @@ class App extends Component { this.state = { apiUrl: url } - } + }*/ // Once the app is mounted componentDidMount() { // load all projects @@ -74,9 +81,8 @@ class App extends Component { // fetch all projcets allProjects = () => { - apiCall.getAllProjects(res => { + api.getAllProjects(res => { if (res.error) {console.error(res.error)} - console.log('res.data', res.data); if (res.data) { this.setState({projects: res.data}); // update state to response data this.props.setProjects(res.data); // redux store @@ -86,8 +92,8 @@ class App extends Component { // get one project by ID getOneProject = (projectId, next) => { // apiCall expects a "null" if projects are not loaded yet - const projects = (this.state.projects.length > 0) ? this.state.projects : null; - apiCall.getProjectById(projects, projectId, res => { + const projects = (this.props.projects.length > 0) ? this.props.projects : null; + api.getProjectById(projects, projectId, res => { if (res.error) {console.error(res.error)} next(res.data); }); @@ -101,23 +107,23 @@ class App extends Component { // update project updateProject = (data) => { console.log('updateProject', data); - apiCall.postProject(data, this.allProjects()); + api.postProject(data, this.allProjects()); } // delete project deleteProject = (data) => { - apiCall.deleteProject(data, this.allProjects()); + api.deleteProject(data, this.allProjects()); } // get one user profile by ID getOneUser = (id, next) => { - apiCall.getUserById(id, res => { + api.getUserById(id, res => { if (res.error) {console.error(res.error)} next(res.data); }); } // updates user data postUser = (data) => { - apiCall.postUser(data, () => { + api.postUser(data, () => { this.allProjects(); this.setUser(); }); @@ -125,7 +131,7 @@ class App extends Component { // get user data from api and assign it to state setUser = () => { console.log('set user'); - apiCall.getCurrentUser(res => { + api.getCurrentUser(res => { console.log('set user response', res); if (res.error) {console.error(res.error)} if (res.data) { From b0c51de71d803955a68bb746fa5144c786793236 Mon Sep 17 00:00:00 2001 From: Shohei Date: Wed, 20 Jun 2018 13:59:25 +0000 Subject: [PATCH 5/8] FE interface and api request function. BE receives request. --- routes/users/users.js | 5 +++-- src/components/molecules/UserInfo.js | 8 +++++--- src/js/apiCalls.js | 13 +++++++++++++ src/js/fakeApi.js | 6 +++++- src/routes.js | 19 +++++++++++++++---- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/routes/users/users.js b/routes/users/users.js index 54e36131..be6263b0 100644 --- a/routes/users/users.js +++ b/routes/users/users.js @@ -91,7 +91,8 @@ router.route('/:user_id') //delete method for removing a user from our database .delete(function(req, res) { - User.findById(req.params.user_id) + console.log('Delete User request', req.params.user_id); +/* User.findById(req.params.user_id) .exec(function (err, user) { if (err) return res.send(err); if (user._id === req.user._id) { @@ -104,7 +105,7 @@ router.route('/:user_id') // user to be deleted is not owned by the logged in user return res.send('Cannot delete account not owned by the user'); } - }) + }) */ }); router.route('/contact/:user_id') diff --git a/src/components/molecules/UserInfo.js b/src/components/molecules/UserInfo.js index de445afc..4114943d 100644 --- a/src/components/molecules/UserInfo.js +++ b/src/components/molecules/UserInfo.js @@ -50,11 +50,13 @@ class UserInfo extends Component { this.props.history.push('/project/view/' + e.target.id); } toggleModal = () => { - console.log('toggle modal', this.state.showModal); this.setState({ showModal: !this.state.showModal }); } + deleteUser = () => { + this.props.onUserDelete(this.props.match.params.id); + } renderInfo = (user, projects) => { if (user) { return ( @@ -126,8 +128,8 @@ class UserInfo extends Component { This will also delete all of your owned projects, and this action cannot be undone.
Are you sure?
- - + +
diff --git a/src/js/apiCalls.js b/src/js/apiCalls.js index eb04827f..297373d4 100644 --- a/src/js/apiCalls.js +++ b/src/js/apiCalls.js @@ -116,6 +116,19 @@ const apiCall = { next({error: err}); throw err; }); + }, + + // delete user + deleteUser(id, next) { + console.log('deleteUser'); + axios.delete(`${apiUrl}/api/users/${id}`) + .then(res => { + next({data: res.data}); + }) + .catch(err => { + next({error: err}); + throw err; + }); } }; diff --git a/src/js/fakeApi.js b/src/js/fakeApi.js index 905b1c17..4537cd35 100644 --- a/src/js/fakeApi.js +++ b/src/js/fakeApi.js @@ -42,11 +42,15 @@ const fakeApi = { console.log('FAKE postProject'); next({data: "FAKE postProject"}); }, - // delete project deleteProject(data, next) { console.log('FAKE deleteProject'); next({data: "FAKE deleteProject"}); + }, + // delete user + deleteUser(id, next) { + console.log('FAKE deleteUser'); + next({data: "FAKE deleteUser Success"}); } }; diff --git a/src/routes.js b/src/routes.js index 6ffed9ad..4e2fc80e 100644 --- a/src/routes.js +++ b/src/routes.js @@ -143,6 +143,19 @@ class App extends Component { } }); } + // delete user + deleteUser = (id) => { + console.log(`delete user ${id}`); + api.deleteUser(id, res => { + if (res.error) { + console.error(res.error); + window.location = '/'; + } else { + console.log(res.data); + window.location = '/'; + } + }) + } // logout the user by setting the app state.user as null logoutUser = () => { // logout user axios.get('/auth/logout').then(()=> { @@ -154,9 +167,6 @@ class App extends Component { window.location = '/'; // and redirects to the homepage }); } - - - // once project is unfollowed or followed, matches the db value without calling db updateUserProjects = (project_id) => { // copy state @@ -242,7 +252,8 @@ class App extends Component { {...{ user: this.props.user, projects: this.props.projects, - getOneUser: this.getOneUser + getOneUser: this.getOneUser, + onUserDelete: this.deleteUser }} /> } }/> From a1f26d934653c2ce26b6d2d34451d88859e77df9 Mon Sep 17 00:00:00 2001 From: Shohei Shibata Date: Thu, 21 Jun 2018 05:58:54 +0200 Subject: [PATCH 6/8] Working on delete user backend code --- routes/users/users.js | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/routes/users/users.js b/routes/users/users.js index be6263b0..29c8f45d 100644 --- a/routes/users/users.js +++ b/routes/users/users.js @@ -6,6 +6,8 @@ const request = require('request'); const User = require('../../model/users'); const userHelpers = require('./userHelpers.js') +const Project = require('../../model/projects'); + // USER ROUTES router.route('/') @@ -45,7 +47,10 @@ router.route('/:user_id') .get(function(req, res) { User.findById(req.params.user_id, function(err, user) { if (err) { res.send(err); } - else { + else if (!user) { + console.log("User not found!"); + res.send("User not found!"); + } else { let user_filtered = { _id: user._id, username: user.username, @@ -54,7 +59,7 @@ router.route('/:user_id') skillset: user.skillset }; // Only if user is requesting own info, share email address. - if (req.user._id === req.params.user_id) { + if (req.user && req.user._id === req.params.user_id) { user_filtered.email = user.email; } // respond with full user data only if logged in. @@ -92,20 +97,31 @@ router.route('/:user_id') //delete method for removing a user from our database .delete(function(req, res) { console.log('Delete User request', req.params.user_id); -/* User.findById(req.params.user_id) + User.findById(req.params.user_id) .exec(function (err, user) { + console.log('User found?', user._id, req.user._id); if (err) return res.send(err); - if (user._id === req.user._id) { + if (String(user._id) == String(req.user._id)) { // user to be deleted is owned by the logged in user - user.remove({ _id: req.params.user_id }, function(err, user) { - if (err) { res.send(err); } - }); + console.log('User to be deleted', user.username); + //user.remove({ _id: req.params.user_id }, function(err, user) { + //if (err) { res.send(err); } + //}); + // also find and remove associated projects + Project.find({ users: { _id: user._id} }) + .exec(function (err, projects) { + console.log('Projects to be deleted', projects); + //projects.remove({}, function(err, doc) { + //if (err) { res.send(err); } + //}) + }); return res.redirect('/'); } else { // user to be deleted is not owned by the logged in user + console.log('logged in user ID does not match user to be deleted'); return res.send('Cannot delete account not owned by the user'); } - }) */ + }) }); router.route('/contact/:user_id') From e356b4bd6209a6d230ff68419db477285f3fc6da Mon Sep 17 00:00:00 2001 From: Shohei Date: Tue, 26 Jun 2018 15:58:30 +0000 Subject: [PATCH 7/8] Backend delets user, owned projects, and following statuses --- routes/follow/follow.js | 6 ++-- routes/users/users.js | 62 +++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/routes/follow/follow.js b/routes/follow/follow.js index 90eb9d32..e15a3f3c 100644 --- a/routes/follow/follow.js +++ b/routes/follow/follow.js @@ -7,6 +7,8 @@ router.route("/:project_id").post(function(req, res) { const { _id: user_id } = req.user; const { project_id } = req.params; + + console.log('Follow/Unfollow Request', project_id, req.user._id); // Find existing project Project.findById(project_id, function(err, project) { @@ -18,7 +20,7 @@ router.route("/:project_id").post(function(req, res) { if (userStatus.status === 'following') { // User is already following. Unfollow. userStatus.remove(); - console.log('Unfollowed', project); + console.log('Unfollowed', project.title); } } else { // User not associated to project @@ -27,7 +29,7 @@ router.route("/:project_id").post(function(req, res) { _id: user_id, status: 'following' }); - console.log('Followed', project); + console.log('Followed', project.title); } project.save(function(err, update) { if (err) throw err; diff --git a/routes/users/users.js b/routes/users/users.js index 29c8f45d..4370b720 100644 --- a/routes/users/users.js +++ b/routes/users/users.js @@ -103,18 +103,58 @@ router.route('/:user_id') if (err) return res.send(err); if (String(user._id) == String(req.user._id)) { // user to be deleted is owned by the logged in user + // Find and remove owned projects + Project.find({ + users: { + $elemMatch: { + _id: user._id, + status: "owner" + } + } + }) + .exec(function (err, projects) { + if (err) throw err; + console.log('Owned projects to be deleted'); + if (projects) { + projects.forEach(function(project) { + console.log(project.title, project.users); + project.remove(); + project.save(function(err, update) { + if (err) throw err; + }); + }) + } + }); + // also find followed projects and remove status + Project.find({ + users: { + $elemMatch: { + _id: user._id, + status: "following" + } + } + }) + .exec(function (err, projects) { + if (err) throw err; + if (projects) { + projects.forEach(function(project) { + //unfollow all followed projects + let status = project.users.id(user._id); + status.remove(); + + project.save(function(err, update) { + if (err) throw err; + }); + }); + + } + }); + // Finally remove user account console.log('User to be deleted', user.username); - //user.remove({ _id: req.params.user_id }, function(err, user) { - //if (err) { res.send(err); } - //}); - // also find and remove associated projects - Project.find({ users: { _id: user._id} }) - .exec(function (err, projects) { - console.log('Projects to be deleted', projects); - //projects.remove({}, function(err, doc) { - //if (err) { res.send(err); } - //}) - }); + user.remove(); + user.save(function(err, update) { + if (err) throw err; + }); return res.redirect('/'); } else { // user to be deleted is not owned by the logged in user From 01d06c7cb27a4a175ed94e6f696d4e32de148b84 Mon Sep 17 00:00:00 2001 From: Shohei Shibata Date: Wed, 27 Jun 2018 05:22:29 +0200 Subject: [PATCH 8/8] Code refactoring and commenting --- routes/users/users.js | 18 ++++-------------- src/js/fakeAuth.js | 11 ----------- src/routes.js | 1 + 3 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 src/js/fakeAuth.js diff --git a/routes/users/users.js b/routes/users/users.js index 4370b720..7168a98f 100644 --- a/routes/users/users.js +++ b/routes/users/users.js @@ -99,12 +99,11 @@ router.route('/:user_id') console.log('Delete User request', req.params.user_id); User.findById(req.params.user_id) .exec(function (err, user) { - console.log('User found?', user._id, req.user._id); if (err) return res.send(err); if (String(user._id) == String(req.user._id)) { // user to be deleted is owned by the logged in user // Find and remove owned projects - Project.find({ + Project.deleteMany({ users: { $elemMatch: { _id: user._id, @@ -112,18 +111,9 @@ router.route('/:user_id') } } }) - .exec(function (err, projects) { + .exec(function (err, res) { if (err) throw err; - console.log('Owned projects to be deleted'); - if (projects) { - projects.forEach(function(project) { - console.log(project.title, project.users); - project.remove(); - project.save(function(err, update) { - if (err) throw err; - }); - }) - } + console.log("Projects deleted", res.deletedCount); }); // also find followed projects and remove status Project.find({ @@ -141,9 +131,9 @@ router.route('/:user_id') //unfollow all followed projects let status = project.users.id(user._id); status.remove(); - project.save(function(err, update) { if (err) throw err; + console.log("Unfollowed projects", update.title); }); }); diff --git a/src/js/fakeAuth.js b/src/js/fakeAuth.js deleted file mode 100644 index 8a03c7bd..00000000 --- a/src/js/fakeAuth.js +++ /dev/null @@ -1,11 +0,0 @@ -const fakeAuth = { - user: { - _id: "12345", - username: "fakeUser", - skillset: ["One", "Two", "Three"], - avatar: "https://picsum.photos/50" - }, - projects: [{"_id":"5a65fd8a3d77f50004decf51","repoUrl":"http://www.ideaswatch.com/startup-idea/fake-at-party-app","status":"I have the idea, but I haven't started coding it yet.","description":"This app creates background noises (e.g. traffic, loud music, people in a party chatting) when you are calling. This is useful when you're ex is calling, so you can pretend you're busy having fun!","owner":"5a6247110173f1000448b79d","title":"Noisr","__v":8,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["NA"],"stack":["Java","Swift"],"categories":["Mobile App"]},{"_id":"5a66116211a5c72408a19281","repoUrl":"NA","status":"It's just an idea","description":"Find coworkers in your area to commute with.","owner":"5a6247110173f1000448b79d","title":"CommuteWithMe","__v":12,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a7b8c2b128e880004cb2dbf","status":"following"}],"img":[],"stack":["React Native"],"categories":["Mobile App"]},{"_id":"5a7b8d82128e880004cb2dc0","repoUrl":"https://github.com/chingu-coders/Voyage2-Turtles-02","status":"Currently complete but we are currently working on V2 which would include a faster DevTab and more features. (Created by Dan Nguyen, Jeff Bothe, Tyler Del Rosario)\nDevTab is a Chingu Project","description":"An awesome new-tab extension designed for Developers","owner":"","title":"DevTab","__v":10,"users":[{"_id":"5a7b8c2b128e880004cb2dbf","status":"owner"}],"img":[],"stack":["HTML","CSS","JS","jQuery","jQuery UI"],"categories":["New-Tab Extension"]},{"_id":"5a7b8eb9128e880004cb2dc1","repoUrl":"https://github.com/chingu-voyage3/bears-06","status":"BearBnB is a completed Chingu Project :D(Created by Vannya, Stephan, Lee)\n ","description":"An open-source clone of AirBnB.","title":"BearBnB","__v":11,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["MERN Stack","Mongo","Express","ReactJS","Node"],"categories":["App Clone"]},{"_id":"5ad5b3a8cdc05a3a50119f28","repoUrl":"http://","status":"Stuck","description":"The most generic project ever","title":"Yet another project","__v":1,"users":[{"_id":"5a9a9139ab060929303bded4","status":"owner"},{"_id":"5af4874738973100045687d3","status":"following"}],"img":[],"stack":["Mern"],"categories":["Web app"]},{"_id":"5af4879838973100045687d4","repoUrl":"http","status":"begin","description":"ever project best","title":"bookface","__v":0,"users":[{"_id":"5af4874738973100045687d3","status":"owner"}],"img":[],"stack":[],"categories":["Web app"]},{"_id":"5a660fbb11a5c72408a1927f","repoUrl":"http://www.ideaswatch.com/startup-idea/rifflord","status":"Idea found on IdeasWatch - never started","description":"Find and connect with musicians around you and form your band. On RiffLord you can upload a sample of your music and browse through musicians living around your area.","title":"RiffLord","__v":2,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5b074a9f2a1ccc0004510e38","status":"following"}],"img":[],"stack":["TBD"],"categories":["Social Network"]},{"_id":"5a663627d1a0785a64e8b6e3","repoUrl":"http://github.com","status":"Just an idea. Looking for devs to build it!","description":"This is a social network for unsociable people. It will text you when someone you DON'T want to meet is nearby.","title":"UnSocial Network","__v":1,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"}],"img":["https://cdn.images.express.co.uk/img/dynamic/80/590x/Grumpy-Cat-on-bed-544409.jpg"],"stack":["HTML","CSS","JavaScript"],"categories":["Web App"]},{"_id":"5a660f1f11a5c72408a1927e","repoUrl":"https://bitbucket.org/AlexGherardelli/evergreen","status":"I got stuck because I could not figure out how to post things on behalf of users with Flask and the Twitter API. I would love to have a more expert developer helping me with this project!","description":"Evergreen is a social media management app that allows you to reschedule your best and most effective posts over and over again, to maximize engagement and exposure. For example, you can schedule a \"Happy New Year\" post and never worry ever again to post it again. Or you can resend the invitation to an event multiple times at different times, so that people in different time zones can see your post.","title":"Evergreen","__v":4,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5a6055120f25ffaa290471fd","status":"following"}],"img":[],"stack":["Flask (Python)","HTML","SCSS/SASS","JavaScript"],"categories":["Social media management"]},{"_id":"5a66109911a5c72408a19280","repoUrl":"https://bitbucket.org/AlexGherardelli/dickens","status":"I have the boilerplate, but I would like a team mate to develop it.","description":"I have read online that with the time people spend on social media, they could read 200 books a year. With this scary stat in mind, I thought it would be nice to build a browser extension that every time you connect to a social media like Facebook, it redirects you toward a short story that can be read in a few minutes. A more productive break indeed!","owner":"5a6247110173f1000448b79d","title":"Dickens","__v":14,"users":[{"_id":"5a6247110173f1000448b79d","status":"owner"},{"_id":"5a9bfa90b2631921458268d7","status":"following"},{"_id":"5acadeeffcadd708d6d029d6","status":"following"}],"img":["https://i2-prod.mirror.co.uk/incoming/article5418983.ece/ALTERNATES/s615/Charles-Dickens.jpg"],"stack":[],"categories":["Browser Extension"]}] -}; - -export default fakeAuth; \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index 4e2fc80e..6008279e 100644 --- a/src/routes.js +++ b/src/routes.js @@ -37,6 +37,7 @@ import Dashboard from './components/molecules/Dashboard'; // Loads environment variables with dotenv require('dotenv').load(); +// Code below triggers fake auth mode for development let api = apiCall; if (process.env.REACT_APP_FAKE) { console.log("***FAKE MODE***");