diff --git a/functions/handlers/post.js b/functions/handlers/post.js index 91190ec..ae839c3 100644 --- a/functions/handlers/post.js +++ b/functions/handlers/post.js @@ -61,6 +61,7 @@ exports.getallPostsforUser = (req, res) => { }; exports.getallPosts = (req, res) => { + var post_query = admin.firestore().collection("posts"); post_query .get() @@ -170,6 +171,7 @@ exports.quoteWithPost = (req, res) => { return res.status(400).json({ error: "Post has already been quoted." }); } }) + .catch(err => { return res.status(500).json({ error: err }); }); @@ -281,6 +283,7 @@ exports.likePost = (req, res) => { return res.status(404).json({ error: "Post not found" }); } }) + .then(data => { if (data.empty) { return admin diff --git a/functions/handlers/users.js b/functions/handlers/users.js index 3430fff..7e63f32 100644 --- a/functions/handlers/users.js +++ b/functions/handlers/users.js @@ -1,4 +1,5 @@ -/* eslint-disable promise/catch-or-return */ +/* eslint-disable promise/always-return */ + const { admin, db } = require("../util/admin"); const config = require("../util/config"); const { validateUpdateProfileInfo } = require("../util/validator"); @@ -209,7 +210,7 @@ exports.deleteUser = (req, res) => { let errors = {}; function thenFunction(data) { - console.log(`${data} data for ${req.userData.handle} has been deleted.`); + console.log(`${data} for ${req.userData.handle} has been deleted.`); } function catchFunction(data, err) { @@ -217,14 +218,131 @@ exports.deleteUser = (req, res) => { errors[data] = err; } + function deleteDirectMessages() { + return new Promise((resolve, reject) => { + const deleteUsername = req.userData.handle; + db.doc(`/users/${deleteUsername}`) + .get() + .then((deleteUserDocSnap) => { + const dms = deleteUserDocSnap.data().dms; + const dmRecipients = deleteUserDocSnap.data().dmRecipients; + + if (!dms) { + resolve(); + return; + } + + // Iterate over the list of users who this person has DM'd + let otherUsersPromises = []; + + // Resolve if they don't have a dmRecipients list + if (dmRecipients === undefined || dmRecipients === null || dmRecipients.length === 0) { + resolve(); + return; + } + dmRecipients.forEach((dmRecipient) => { + otherUsersPromises.push( + // Get each users data + db.doc(`/users/${dmRecipient}`).get() + .then((otherUserDocSnap) => { + // Get the index of deleteUsername so that we can remove the dangling + // reference to the DM document + let otherUserDMRecipients = otherUserDocSnap.data().dmRecipients; + let otherUserDMs = otherUserDocSnap.data().dms; + let index = -1; + otherUserDMRecipients.forEach((dmRecip, i) => { + if (dmRecip === deleteUsername) { + index = i; + } + }) + + if (index !== -1) { + // Remove deleteUsername from their dmRecipients list + otherUserDMRecipients.splice(index, 1); + + // Remove the DM channel with deleteUsername + otherUserDMs.splice(index, 1); + + // Update the users data + return otherUserDocSnap.ref.update({ + dmRecipients: otherUserDMRecipients, + dms: otherUserDMs + }); + } + + }) + ) + }) + + // Wait for the removal of DM data stored on other users to be deleted + Promise.all(otherUsersPromises) + .then(() => { + // Iterate through DM references and delete them from the dm collection + let dmRefsPromises = []; + dms.forEach((dmRef) => { + // Create a delete queue + let batch = db.batch(); + dmRefsPromises.push( + // Add the messages to the delete queue + db.collection(`/dm/${dmRef.id}/messages`).listDocuments() + .then((docs) => { + console.log("second") + console.log(docs); + docs.map((doc) => { + batch.delete(doc); + }) + + // Add the doc that the DM is stored in to the delete queue + batch.delete(dmRef); + + // Commit the writes + return batch.commit(); + }) + ) + }) + + return Promise.all(dmRefsPromises); + }) + .then(() => { + resolve(); + return; + }) + .catch((err) => { + console.log("error " + err); + reject(err); + return; + }) + }) + .catch((err) => { + console.log(err); + return res.status(500).json({error: err}); + }) + + }) + } + // Deletes user from authentication let auth = admin.auth().deleteUser(userId); // Deletes database data - let data = db - .collection("users") - .doc(`${req.user.handle}`) - .delete(); + let data = new Promise((resolve, reject) => { + deleteDirectMessages() + .then(() => { + return db + .collection("users") + .doc(`${req.user.handle}`) + .delete() + }) + .then(() => { + resolve(); + return; + }) + .catch((err) => { + console.log(err); + reject(err); + return; + }) + }) // Deletes any custom profile image let image; @@ -507,6 +625,7 @@ exports.removeSub = (req, res) => { .catch(err => { return res.status(500).json({ err }); }); + return res.status(200).json({ message: "ok" }); }); }; diff --git a/twistter-frontend/package.json b/twistter-frontend/package.json index 75afcb0..52e50f3 100644 --- a/twistter-frontend/package.json +++ b/twistter-frontend/package.json @@ -43,5 +43,5 @@ "last 1 safari version" ] }, - "proxy": "http://localhost:5006/twistter-e4649/us-central1/api" + "proxy": "http://localhost:5001/twistter-e4649/us-central1/api" } diff --git a/twistter-frontend/src/Userline.js b/twistter-frontend/src/Userline.js index 8c95620..6c61d6d 100644 --- a/twistter-frontend/src/Userline.js +++ b/twistter-frontend/src/Userline.js @@ -1,10 +1,10 @@ import React, { Component } from "react"; -import { BrowserRouter as Router } from 'react-router-dom'; -import Route from 'react-router-dom/Route'; +// import { BrowserRouter as Router } from 'react-router-dom'; +// import Route from 'react-router-dom/Route'; import axios from 'axios'; import Box from '@material-ui/core/Box' -import {borders} from '@material-ui/system'; -import { sizing } from '@material-ui/system'; +// import {borders} from '@material-ui/system'; +// import { sizing } from '@material-ui/system'; // var moment = require('moment'); @@ -41,7 +41,7 @@ class Userline extends Component {

Userline

- +

{sortedPosts.map((microBlog) =>

Microblog Title: {microBlog.microBlogTitle} @@ -50,7 +50,7 @@ class Userline extends Component {

Number of comments: {microBlog.commentCount}

Number of likes: {microBlog.likeCount}

Body of post: {microBlog.body} -

Tagged topics: {microBlog.microBlogTopics.join("," + " ")} +

Tagged topics: {microBlog.microBlogTopics.join(", ")}

)}

diff --git a/twistter-frontend/src/Writing_Microblogs.js b/twistter-frontend/src/Writing_Microblogs.js index 2283e61..70b67d0 100644 --- a/twistter-frontend/src/Writing_Microblogs.js +++ b/twistter-frontend/src/Writing_Microblogs.js @@ -1,11 +1,11 @@ import React, { Component } from "react"; -import { BrowserRouter as Router } from "react-router-dom"; -import Route from "react-router-dom/Route"; +// import { BrowserRouter as Router } from "react-router-dom"; +// import Route from "react-router-dom/Route"; import axios from "axios"; // Material-UI import TextField from '@material-ui/core/TextField'; -import Typography from '@material-ui/core/Typography'; +// import Typography from '@material-ui/core/Typography'; import Button from '@material-ui/core/Button'; import withStyles from "@material-ui/styles/withStyles"; @@ -127,7 +127,6 @@ class Writing_Microblogs extends Component { fullWidth autoComplete='off' /> - { - console.log(res.data); + // console.log(res.data); this.setState({ posts: res.data }); @@ -57,7 +57,7 @@ class Home extends Component { let postMarkup = this.state.posts ? ( this.state.posts.map(post => - + { @@ -85,8 +85,9 @@ class Home extends Component {

Loading post...

); - return authenticated ? ( - + return ( + authenticated ? ( + @@ -121,7 +122,7 @@ class Home extends Component { - ); + )); } } @@ -342,7 +343,7 @@ const mapStateToProps = (state) => ({ Home.propTypes = { user: PropTypes.object.isRequired, - clases: PropTypes.object.isRequired, + classes: PropTypes.object.isRequired, UI: PropTypes.object.isRequired } diff --git a/twistter-frontend/src/pages/Login.js b/twistter-frontend/src/pages/Login.js index fbf2c68..acdff3e 100644 --- a/twistter-frontend/src/pages/Login.js +++ b/twistter-frontend/src/pages/Login.js @@ -110,7 +110,7 @@ export class Login extends Component { logo

- + Log in to Twistter

diff --git a/twistter-frontend/src/pages/Search.js b/twistter-frontend/src/pages/Search.js index c8409f5..c6b9e70 100644 --- a/twistter-frontend/src/pages/Search.js +++ b/twistter-frontend/src/pages/Search.js @@ -1,6 +1,7 @@ import React, { Component } from "react"; // import props -import { TextField, Button } from "@material-ui/core"; +// import { TextField, Button } from "@material-ui/core"; +import TextField from "@material-ui/core/TextField" import Grid from "@material-ui/core/Grid"; import axios from "axios"; import Fuse from "fuse.js"; @@ -38,7 +39,7 @@ export class Search extends Component { handles: res.data, loading: false }, () => { - console.log(res.data); + // console.log(res.data); fuse = new Fuse(this.state.handles, fuseOptions); // "list" is the item array }) }) @@ -65,7 +66,7 @@ export class Search extends Component { let result = fuse.search(event.target.value); let parsed = []; result.forEach((res) => { - console.log(res) + // console.log(res) parsed.push(this.state.handles[res]) }) this.setState({ @@ -80,7 +81,7 @@ export class Search extends Component { render() { let resultMarkup = this.state.searchResult && this.state.searchResult !== "No Results" ? ( this.state.searchResult.map(res => - +
{res} diff --git a/twistter-frontend/src/pages/user.js b/twistter-frontend/src/pages/user.js index 7a8f929..6a189b6 100644 --- a/twistter-frontend/src/pages/user.js +++ b/twistter-frontend/src/pages/user.js @@ -76,7 +76,7 @@ class user extends Component { profile: null, imageUrl: null, topics: null, - newTopic: null + newTopic: "" }; } @@ -179,7 +179,7 @@ class user extends Component { topic => ( this.handleDelete(topic)} /> ) // console.log({ topic }.topic.id) @@ -206,7 +206,7 @@ class user extends Component { let postMarkup = this.state.posts ? ( this.state.posts.map(post => ( - + {this.state.imageUrl ? ( @@ -215,7 +215,7 @@ class user extends Component { )} - + {post.userHandle} @@ -285,7 +285,7 @@ class user extends Component { @@ -321,7 +321,7 @@ const mapStateToProps = state => ({ user.propTypes = { user: PropTypes.object.isRequired, - clases: PropTypes.object.isRequired + classes: PropTypes.object.isRequired }; export default connect(mapStateToProps)(withStyles(styles)(user)); diff --git a/twistter-frontend/src/pages/verify.js b/twistter-frontend/src/pages/verify.js index e36a317..88a804e 100644 --- a/twistter-frontend/src/pages/verify.js +++ b/twistter-frontend/src/pages/verify.js @@ -89,7 +89,7 @@ export class verify extends Component { render() { const { classes } = this.props; - const { errors, loading } = this.state; + const { loading } = this.state; return ( diff --git a/twistter-frontend/src/redux/actions/userActions.js b/twistter-frontend/src/redux/actions/userActions.js index 7fc6cbf..832e9fa 100644 --- a/twistter-frontend/src/redux/actions/userActions.js +++ b/twistter-frontend/src/redux/actions/userActions.js @@ -1,6 +1,18 @@ -import {SET_USER, SET_ERRORS, CLEAR_ERRORS, LOADING_UI, SET_AUTHENTICATED, SET_UNAUTHENTICATED} from '../types'; +import { + SET_USER, + SET_ERRORS, + CLEAR_ERRORS, + LOADING_UI, + // SET_AUTHENTICATED, + SET_UNAUTHENTICATED +} from '../types'; import axios from 'axios'; +const setAuthorizationHeader = (token) => { + const FBIdToken = `Bearer ${token}`; + localStorage.setItem('FBIdToken', FBIdToken); + axios.defaults.headers.common['Authorization'] = FBIdToken; +} export const getUserData = () => (dispatch) => { axios.get('/user') @@ -81,9 +93,3 @@ export const deleteUser = () => (dispatch) => { delete axios.defaults.headers.common['Authorization']; dispatch({ type: SET_UNAUTHENTICATED }); } - -const setAuthorizationHeader = (token) => { - const FBIdToken = `Bearer ${token}`; - localStorage.setItem('FBIdToken', FBIdToken); - axios.defaults.headers.common['Authorization'] = FBIdToken; -} \ No newline at end of file diff --git a/twistter-frontend/src/redux/reducers/userReducer.js b/twistter-frontend/src/redux/reducers/userReducer.js index 7a29e90..e26509a 100644 --- a/twistter-frontend/src/redux/reducers/userReducer.js +++ b/twistter-frontend/src/redux/reducers/userReducer.js @@ -1,4 +1,11 @@ -import {SET_USER, SET_ERRORS, CLEAR_ERRORS, LOADING_UI, SET_AUTHENTICATED, SET_UNAUTHENTICATED} from '../types'; +import { + SET_USER, + // SET_ERRORS, + // CLEAR_ERRORS, + // LOADING_UI, + SET_AUTHENTICATED, + SET_UNAUTHENTICATED +} from '../types'; const initialState = { authenticated: false,