diff --git a/functions/handlers/post.js b/functions/handlers/post.js
index d15ea33..5f361fe 100644
--- a/functions/handlers/post.js
+++ b/functions/handlers/post.js
@@ -1,7 +1,6 @@
-const admin = require('firebase-admin');
/* eslint-disable promise/always-return */
+const admin = require('firebase-admin');
exports.putPost = (req, res) => {
-
const newPost = {
body: req.body.body,
@@ -11,6 +10,7 @@ exports.putPost = (req, res) => {
createdAt: new Date().toISOString(),
likeCount: 0,
commentCount: 0,
+ microBlogTopics: req.body.microBlogTopics
};
@@ -28,7 +28,7 @@ exports.putPost = (req, res) => {
exports.getallPostsforUser = (req, res) => {
- admin.firestore().collection('posts').where('userHandle', '==', 'user' ).get()
+ admin.firestore().collection('posts').where('userHandle', '==', 'new user' ).get()
.then((data) => {
let posts = [];
data.forEach(function(doc) {
@@ -41,5 +41,3 @@ exports.getallPostsforUser = (req, res) => {
return res.status(500).json({error: 'Failed to fetch all posts written by specific user.'})
})
}
-
-
diff --git a/functions/handlers/users.js b/functions/handlers/users.js
index 2a83ee7..cdeb3f6 100644
--- a/functions/handlers/users.js
+++ b/functions/handlers/users.js
@@ -1,210 +1,216 @@
/* eslint-disable promise/catch-or-return */
-const {admin, db} = require('../util/admin');
-const config = require('../util/config');
+const { admin, db } = require("../util/admin");
+const config = require("../util/config");
+const { validateUpdateProfileInfo } = require("../util/validator");
-const {validateUpdateProfileInfo} = require('../util/validator');
-
-const firebase = require('firebase');
+const firebase = require("firebase");
firebase.initializeApp(config);
-
-
exports.signup = (req, res) => {
- const newUser = {
+ const newUser = {
+ email: req.body.email,
+ handle: req.body.handle,
+ password: req.body.password,
+ confirmPassword: req.body.confirmPassword,
+ createdAt: new Date().toISOString()
+ };
+
+ let errors = {};
+
+ const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+
+ // Email check
+ if (newUser.email.trim() === "") {
+ errors.email = "Email must not be blank.";
+ } else if (!newUser.email.match(emailRegEx)) {
+ errors.email = "Email is invalid.";
+ }
+
+ // handle check
+ if (newUser.handle.trim() === "") {
+ errors.handle = "Username must not be blank.";
+ } else if (newUser.handle.length < 4 || newUser.handle.length > 30) {
+ errors.handle = "Username must be between 4-30 characters long.";
+ }
+
+ // Password check
+ if (newUser.password.trim() === "") {
+ errors.password = "Password must not be blank.";
+ } else if (newUser.password.length < 8 || newUser.password.length > 20) {
+ errors.password = "Password must be between 8-20 characters long.";
+ }
+
+ // Confirm password check
+ if (newUser.confirmPassword !== newUser.password) {
+ errors.confirmPassword = "Passwords must match.";
+ }
+
+ // Overall check
+ if (Object.keys(errors).length > 0) {
+ return res.status(400).json(errors);
+ }
+
+ let idToken, userId;
+
+ db.doc(`/users/${newUser.handle}`)
+ .get()
+ .then((doc) => {
+ if (doc.exists) {
+ return res
+ .status(400)
+ .json({ handle: "This username is already taken." });
+ }
+ return firebase
+ .auth()
+ .createUserWithEmailAndPassword(newUser.email, newUser.password);
+ })
+ .then((data) => {
+ userId = data.user.uid;
+ return data.user.getIdToken();
+ })
+ .then((token) => {
+ idToken = token;
+ const userCred = {
email: req.body.email,
- handle: req.body.handle,
- password: req.body.password,
- confirmPassword: req.body.confirmPassword,
- createdAt: new Date().toISOString()
- };
-
- // console.log(newUser);
-
- let errors = {};
-
- const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
-
- //Email check
- if(newUser.email.trim() === '') {
- errors.email = 'Email must not be blank.';
- }
- else if(!newUser.email.match(emailRegEx)) {
- errors.email = 'Email is invalid.';
- }
-
- //handle check
- if(newUser.handle.trim() === '') {
- errors.handle = 'Username must not be blank.';
- }
- else if(newUser.handle.length < 4 || newUser.handle.length > 30) {
- errors.handle = 'Username must be between 4-30 characters long.';
- }
-
- //Password check
- if(newUser.password.trim() === '') {
- errors.password = 'Password must not be blank.';
- }
- else if(newUser.password.length < 8 || newUser.password.length > 20) {
- errors.password = 'Password must be between 8-20 characters long.';
- }
-
- //Confirm password check
- if(newUser.confirmPassword !== newUser.password) {
- errors.confirmPassword = 'Passwords must match.';
- }
-
- //Overall check
- if(Object.keys(errors).length > 0) {
- return res.status(400).json(errors);
- }
-
- let idToken, userId;
-
- db.doc(`/users/${newUser.handle}`).get()
- .then(doc => {
- if(doc.exists) {
- return res.status(400).json({ handle: 'This username is already taken.' });
- }
- return firebase.auth().createUserWithEmailAndPassword(newUser.email, newUser.password);
- })
- .then(data => {
- userId = data.user.uid;
- return data.user.getIdToken();
- })
- .then(token => {
- idToken = token;
- const userCred = {
- email: req.body.email,
- handle: newUser.handle,
- createdAt: newUser.createdAt,
- userId
- }
- return db.doc(`/users/${newUser.handle}`).set(userCred);
+ handle: newUser.handle,
+ createdAt: newUser.createdAt,
+ userId
+ };
+ return db.doc(`/users/${newUser.handle}`).set(userCred);
})
.then(() => {
- return res.status(201).json({ idToken });
+ return res.status(201).json({ idToken });
})
- .catch(err => {
- console.error(err);
- if(err.code === 'auth/email-already-in-use') {
- return res.status(500).json({ email: 'This email is already taken.' });
- }
- return res.status(500).json({ error: err.code });
+ .catch((err) => {
+ console.error(err);
+ if (err.code === "auth/email-already-in-use") {
+ return res.status(500).json({ email: "This email is already taken." });
+ }
+ return res.status(500).json({ error: err.code });
});
};
exports.login = (req, res) => {
- const user = {
- email: req.body.email,
- password: req.body.password
- }
-
- //Auth validation
- let errors = {};
-
- //Email check
- if(user.email.trim() === '') {
- errors.email = 'Email must not be blank.';
- }
-
- //Password check
- if(user.password.trim() === '') {
- errors.password = 'Password must not be blank.';
- }
-
- //Overall check
- if(Object.keys(errors).length > 0) {
- return res.status(400).json(errors);
- }
-
- firebase.auth().signInWithEmailAndPassword(user.email, user.password)
- .then(data => {
- return data.user.getIdToken();
- })
- .then(token => {
- return res.json({token});
- })
- .catch(err => {
- console.error(err);
- if(err.code === 'auth/wrong-password') {
- return res.status(403).json({ general: 'Invalid credentials. Please try again.' });
- }
- return res.status(500).json({ error: err.code });
- });
- };
+ const user = {
+ email: req.body.email,
+ password: req.body.password
+ };
-exports.getProfileInfo = (req, res) => {
- // FIXME: Delete this after login is implemented
- req.user = {};
- req.user.handle = 'itsjimmy';
+ // Auth validation
+ let errors = {};
- db.collection('users').doc(req.user.handle).get()
- .then((data) => {
- return res.status(200).json(data.data());
- })
- .catch((err) => {
- console.error(err);
- return res.status(500).json(err);
- });
+ // Email check
+ if (user.email.trim() === "") {
+ errors.email = "Email must not be blank.";
+ }
+
+ // Password check
+ if (user.password.trim() === "") {
+ errors.password = "Password must not be blank.";
+ }
+
+ // Checking if any errors have been raised
+ if (Object.keys(errors).length > 0) {
+ return res.status(400).json(errors);
+ }
+
+ firebase
+ .auth()
+ .signInWithEmailAndPassword(user.email, user.password)
+ .then((data) => {
+ return data.user.getIdToken();
+ })
+ .then((token) => {
+ return res.json({ token });
+ })
+ .catch((err) => {
+ console.error(err);
+ if (err.code === "auth/wrong-password") {
+ return res
+ .status(403)
+ .json({ general: "Invalid credentials. Please try again." });
+ }
+ return res.status(500).json({ error: err.code });
+ });
};
+// Returns all data in the database for the user who is currently signed in
+exports.getProfileInfo = (req, res) => {
+ db.collection("users")
+ .doc(req.user.handle)
+ .get()
+ .then((data) => {
+ return res.status(200).json(data.data());
+ })
+ .catch((err) => {
+ console.error(err);
+ return res.status(500).json(err);
+ });
+};
+
+// Updates the data in the database of the user who is currently logged in
exports.updateProfileInfo = (req, res) => {
- // FIXME: Delete this after login is implemented
- req.user = {};
- req.user.handle = 'itsjimmy';
+ // TODO: Add functionality for adding/updating profile images
- // TODO: Add functionality for adding/updating profile images
+ // Data validation
+ const { valid, errors, profileData } = validateUpdateProfileInfo(req.body);
+ if (!valid) return res.status(400).json(errors);
-
- // Data validation
- const {valid, errors, profileData} = validateUpdateProfileInfo(req.body);
- if (!valid) return res.status(400).json(errors);
-
-
- // Update the database entry for this user
- db.collection('users').doc(req.user.handle).set(profileData, {merge: true})
- .then(() => {
- console.log(`${req.user.handle}'s profile info has been updated.`)
- return res.status(201).json({general: `${req.user.handle}'s profile info has been updated.`});
- })
- .catch((err) => {
- console.error(err);
- return res.status(500).json({
- error: 'Error updating profile data'
- });
- })
+ // Update the database entry for this user
+ db.collection("users")
+ .doc(req.user.handle)
+ .set(profileData, { merge: true })
+ .then(() => {
+ console.log(`${req.user.handle}'s profile info has been updated.`);
+ return res
+ .status(201)
+ .json({
+ general: `${req.user.handle}'s profile info has been updated.`
+ });
+ })
+ .catch((err) => {
+ console.error(err);
+ return res.status(500).json({
+ error: "Error updating profile data"
+ });
+ });
};
exports.getUserDetails = (req, res) => {
- let userData = {};
- db.doc(`/users/${req.params.handle}`).get().then((doc) => {
- if (doc.exists) {
- userData.user = doc.data();
- return db.collection('post').where('userHandle', '==', req.params.handle)
- .orderBy('createdAt', 'desc').get();
- } else {
- return res.status(404).json({
- error: 'User not found'
- });
- }
- })
- .then((data) => {
- userData.posts = [];
- data.forEach((doc) => {
- userData.posts.push({
- body: doc.data().body,
- createAt: doc.data().createAt,
- userHandle: doc.data().userHandle,
- userImage: doc.data().userImage,
- likeCount: doc.data().likeCount,
- commentCount: doc.data().commentCount,
- postId: doc.id
- });
- });
- return res.json(userData);
- })
- .catch((err) => {
- console.error(err);
- return res.status(500).json({ error: err.code});
+ let userData = {};
+ db.doc(`/users/${req.params.handle}`)
+ .get()
+ .then((doc) => {
+ if (doc.exists) {
+ userData.user = doc.data();
+ return db
+ .collection("post")
+ .where("userHandle", "==", req.params.handle)
+ .orderBy("createdAt", "desc")
+ .get();
+ } else {
+ return res.status(404).json({
+ error: "User not found"
});
+ }
+ })
+ .then((data) => {
+ userData.posts = [];
+ data.forEach((doc) => {
+ userData.posts.push({
+ body: doc.data().body,
+ createAt: doc.data().createAt,
+ userHandle: doc.data().userHandle,
+ userImage: doc.data().userImage,
+ likeCount: doc.data().likeCount,
+ commentCount: doc.data().commentCount,
+ postId: doc.id
+ });
+ });
+ return res.json(userData);
+ })
+ .catch((err) => {
+ console.error(err);
+ return res.status(500).json({ error: err.code });
+ });
};
diff --git a/functions/index.js b/functions/index.js
index 04d3b4e..eb99cbf 100644
--- a/functions/index.js
+++ b/functions/index.js
@@ -1,49 +1,47 @@
/* eslint-disable promise/always-return */
-const functions = require('firebase-functions');
-const app = require('express')();
-const cors = require('cors');
+const app = require("express")();
+const cors = require("cors");
+const { db } = require("./util/admin");
+const fbAuth = require("./util/fbAuth");
+const functions = require("firebase-functions");
app.use(cors());
-const fbAuth = require('./util/fbAuth');
-
-
-const {db} = require('./util/admin');
-
-// const firebase = require('firebase');
-// firebase.initializeApp(config);
-
-
-
-
-
/*------------------------------------------------------------------*
-* handlers/users.js *
-*------------------------------------------------------------------*/
-const {getUserDetails, getProfileInfo, updateProfileInfo, signup, login} = require('./handlers/users');
+ * handlers/users.js *
+ *------------------------------------------------------------------*/
+const {
+ getUserDetails,
+ getProfileInfo,
+ login,
+ signup,
+ updateProfileInfo
+} = require("./handlers/users");
-app.post('/signup', signup);
+// Adds a user to the database and registers them in firebase with
+// an email and password pair
+// Returns a token for the new user
+app.post("/signup", signup);
-app.post('/login', login);
+// Returns a token for the user that matches the provided username
+// and password
+app.post("/login", login);
-app.get('/getUser/:handle', getUserDetails);
+app.get("/getUser/:handle", getUserDetails);
// Returns all profile data of the currently logged in user
-// TODO: Add fbAuth
-app.get('/getProfileInfo', getProfileInfo);
+app.get("/getProfileInfo", fbAuth, getProfileInfo);
// Updates the currently logged in user's profile information
-// TODO: Add fbAuth
-app.post('/updateProfileInfo', updateProfileInfo);
+app.post("/updateProfileInfo", fbAuth, updateProfileInfo);
/*------------------------------------------------------------------*
* handlers/post.js *
*------------------------------------------------------------------*/
-const {putPost, getallPostsforUser} = require('./handlers/post');
+const { getallPostsforUser, putPost } = require("./handlers/post");
-app.get('/getallPostsforUser', getallPostsforUser);
+app.get("/getallPostsforUser", getallPostsforUser);
// Adds one post to the database
-app.post('/putPost', fbAuth, putPost);
+app.post("/putPost", fbAuth, putPost);
-
-exports.api = functions.https.onRequest(app);
\ No newline at end of file
+exports.api = functions.https.onRequest(app);
diff --git a/functions/util/admin.js b/functions/util/admin.js
index 2431f09..ca7191d 100644
--- a/functions/util/admin.js
+++ b/functions/util/admin.js
@@ -1,5 +1,4 @@
const admin = require('firebase-admin');
-
admin.initializeApp();
const db = admin.firestore();
diff --git a/functions/util/config.js b/functions/util/config.js
index 903fed5..6014967 100644
--- a/functions/util/config.js
+++ b/functions/util/config.js
@@ -6,4 +6,4 @@ module.exports = {
storageBucket: "twistter-e4649.appspot.com",
messagingSenderId: "20131817365",
appId: "1:20131817365:web:633c95fb08b16d4526b89c"
-};
\ No newline at end of file
+};
diff --git a/functions/util/validator.js b/functions/util/validator.js
index 3ab6226..c2b1240 100644
--- a/functions/util/validator.js
+++ b/functions/util/validator.js
@@ -1,36 +1,36 @@
-const isEmpty = (str) => {
- if (str.trim() === '') return true;
- else return false;
+const isEmail = (str) => {
+ const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ if (str.match(emailRegEx)) return true;
+ else return false;
};
-const isEmail = (str) => {
- const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
- if (str.match(emailRegEx)) return true;
- else return false;
-}
+const isEmpty = (str) => {
+ if (str.trim() === "") return true;
+ else return false;
+};
exports.validateUpdateProfileInfo = (data) => {
- let errors = {};
- let profileData = {};
+ let errors = {};
+ let profileData = {};
- // ?: Should users be able to change their handles and emails?
+ // ?: Should users be able to change their handles and emails?
- // Only adds the key to the DB if the values are not empty
- if (!isEmpty(data.firstName)) profileData.firstName = data.firstName.trim();
- if (!isEmpty(data.lastName)) profileData.lastName = data.lastName.trim();
- if (!isEmpty(data.bio)) profileData.bio = data.bio.trim();
+ // Only adds the key to the database if the values are not empty
+ if (!isEmpty(data.firstName)) profileData.firstName = data.firstName.trim();
+ if (!isEmpty(data.lastName)) profileData.lastName = data.lastName.trim();
+ if (!isEmpty(data.bio)) profileData.bio = data.bio.trim();
- if (isEmpty(data.email)) {
- errors.email = "Must not be empty.";
- } else if (!isEmail(data.email)) {
- errors.email = "Must be a valid email."
- } else {
- profileData.email = data.email;
- }
+ if (isEmpty(data.email)) {
+ errors.email = "Must not be empty.";
+ } else if (!isEmail(data.email)) {
+ errors.email = "Must be a valid email.";
+ } else {
+ profileData.email = data.email;
+ }
- return {
- errors,
- valid: Object.keys(errors).length === 0 ? true : false,
- profileData
- }
-};
\ No newline at end of file
+ return {
+ errors,
+ valid: Object.keys(errors).length === 0 ? true : false,
+ profileData
+ };
+};
diff --git a/twistter-frontend/src/App.css b/twistter-frontend/src/App.css
index 55d854d..0312f35 100644
--- a/twistter-frontend/src/App.css
+++ b/twistter-frontend/src/App.css
@@ -1,7 +1,3 @@
-/* body {
-
-} */
-
.app {
font-family: "Segoe UI";
font-size: large;
@@ -49,4 +45,5 @@
.container {
margin: 80px auto 0 auto;
max-width: 1200px;
-}
\ No newline at end of file
+ color: #1da1f2;
+}
diff --git a/twistter-frontend/src/App.js b/twistter-frontend/src/App.js
index 27042e7..e69de29 100644
--- a/twistter-frontend/src/App.js
+++ b/twistter-frontend/src/App.js
@@ -1,42 +0,0 @@
-/* eslint-disable */
-import React, { Component } from 'react';
-
-import './App.css';
-
-import { BrowserRouter as Router } from 'react-router-dom';
-import Route from 'react-router-dom/Route';
-
-import NavBar, { Navbar } from './components/layout/NavBar';
-
-import home from './Home.js';
-import register from './Register.js';
-import login from './Login.js';
-import user from './pages/user';
-import writeMicroblog from './Writing_Microblogs.js';
-import userLine from './Userline.js';
-import logout from './Logout.js'
-
-class App extends Component {
- render() {
- return (
-
{microBlog.body}
)} -Userline
++ {sortedPosts.map((microBlog) =>
Microblog Title: {microBlog.microBlogTitle}
+
When post was created: {microBlog.createdAt.substring(0,10) +
+ " " + microBlog.createdAt.substring(11,19)}
+
Number of comments: {microBlog.commentCount}
+
Number of likes: {microBlog.likeCount}
+
Body of post: {microBlog.body}
+
Tagged topics: {microBlog.microBlogTopics.join("," + " ")}
+