screamoviolence 2 jaren geleden
bovenliggende
commit
a35c7d83b5

+ 1 - 0
server/.env

@@ -0,0 +1 @@
+CONNECTION_URL = mongodb+srv://screamoviolence:I9aFxGdAAHkX5l82@social-network.rweq2.mongodb.net/myFullStackSocialNetwork?retryWrites=true&w=majority

+ 2 - 0
server/.env.example

@@ -0,0 +1,2 @@
+PORT = 'port
+CONNECTION_URL = 'mongo key'

+ 1 - 0
server/.gitignore

@@ -0,0 +1 @@
+node_modules

+ 14 - 0
server/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+    "configurations": [
+        
+    {
+        "name": "Launch Program",
+        "program": "${workspaceFolder}/index.js",
+        "request": "launch",
+        "skipFiles": [
+            "<node_internals>/**"
+        ],
+        "type": "pwa-node"
+    }
+    ]
+}

+ 1 - 0
server/Procfile

@@ -0,0 +1 @@
+web: npm run start

+ 82 - 0
server/controllers/posts.js

@@ -0,0 +1,82 @@
+import mongoose from "mongoose";
+import PostMessage from "../models/postMessage.js";
+
+export const getPosts = async (req, res) => {
+  try {
+    const postMessages = await PostMessage.find(); //schema things
+    res.status(200).json(postMessages.reverse());
+  } catch (error) {
+    res.status(404).json({ message: error.message });
+  }
+};
+export const createPost = async (req, res) => {
+  const post = req.body;
+debugger
+  const newPostMessage = new PostMessage({
+    ...post,
+    creator: req.userId,
+    createdAt: new Date().toISOString(),
+  });
+
+  try {
+    await newPostMessage.save();
+    res.status(201).json(newPostMessage);
+  } catch (error) {
+    res.status(409).json({ message: error.message });
+  }
+};
+
+export const updatePost = async (req, res) => {
+  const { id } = req.params;
+  const { title, message, creator, selectedFile } = req.body;
+
+  if (!mongoose.Types.ObjectId.isValid(id)) {
+    return res.status(404).send("No post with that id");
+  }
+
+  const updatedPost = { creator, title, message, selectedFile, _id: id };
+
+
+  await PostMessage.findByIdAndUpdate(id, updatedPost, { new: true });
+
+  res.json(updatedPost);
+};
+
+export const deletePost = async (req, res) => {
+  const { id } = req.params;
+
+  if (!mongoose.Types.ObjectId.isValid(id)) {
+    return res.status(404).send("No post with that id");
+  }
+
+  await PostMessage.findByIdAndDelete(id);
+
+  res.json({ message: "Post deleted success" });
+};
+
+export const likePost = async (req, res) => {
+  const { id } = req.params;
+
+  if (!req.userId) return res.json({ message: "Unauthenticated" });
+
+  if (!mongoose.Types.ObjectId.isValid(id)) {
+    return res.status(404).send("No post with that id");
+  }
+  const post = await PostMessage.findById(id);
+  const index = post.likes.findIndex((id) => id === String(req.userId));
+
+  if (index === -1) {
+    post.likes.push(req.userId);
+  } else {
+    post.likes = post.likes.filter((id) => {
+     return id !== String(req.userId);
+    });
+    
+  }
+
+  const updatedPost = await PostMessage.findByIdAndUpdate(id, post, {
+    new: true,
+  });
+
+  res.status(200).json(updatedPost);
+};

+ 49 - 0
server/controllers/profile.js

@@ -0,0 +1,49 @@
+import mongoose from "mongoose";
+
+import Profile from "../models/profile.js";
+
+export const getProfiles = async (req, res) => {
+  try {
+    const users = await Profile.find().populate("user", ["name", "avatar"]);
+
+    res.status(200).json(users.reverse());
+  } catch (error) {
+    res.status(404).json({ message: error.message });
+  }
+};
+
+export const getProfile = async (req, res) => {
+  try {
+    const profile = await Profile.findOne({
+      user: req.userId,
+    }).populate("user", ["name", "avatar"]);
+    if (!profile) {
+      return res.status(400).json({ msg: "There is no profile for this user" });
+    }
+
+    res.json(profile);
+  } catch (err) {
+    console.error(err.message);
+    res.status(500).send("Server Error");
+  }
+};
+
+export const updateProfile = async (req, res) => {
+  const { bio, age, contacts } = req.body;
+
+  if (!mongoose.Types.ObjectId.isValid(req.userId)) {
+    return res.status(404).send("No profile with that id");
+  }
+
+  const updatedProfile = { bio, age, contacts, _id: req.userId };
+  console.log(updatedProfile);
+  await Profile.findByIdAndUpdate(
+    {
+      user: req.userId,
+    },
+    updatedProfile,
+    { new: true }
+  ).populate("user", ["name", "avatar"]);
+
+  res.json(updatedProfile);
+};

+ 70 - 0
server/controllers/user.js

@@ -0,0 +1,70 @@
+import bcrypt from "bcryptjs";
+import jwt from "jsonwebtoken";
+import Profile from "../models/profile.js";
+import User from "../models/user.js";
+
+export const signin = async (req, res) => {
+  const { email, password } = req.body;
+  try {
+    const existingUser = await User.findOne({ email });
+    if (!existingUser)
+      return res
+        .status(404)
+        .json({ message: "User with this email doesnt exist" });
+    const isPasswordCorrect = await bcrypt.compare(
+      password,
+      existingUser.password
+    );
+    if (!isPasswordCorrect)
+      return res.status(400).json({ message: "Invalid credentials" });
+    const token = jwt.sign(
+      { email: existingUser.email, id: existingUser._id },
+      "sometext"
+    );
+    res.status(200).json({ result: existingUser, token });
+  } catch (error) {
+    res.status(500).json({ message: "something went wrong" });
+  }
+};
+
+export const signup = async (req, res) => {
+  const { email, password, confirmPassword, firstName, lastName } = req.body;
+  const profileFields = {};
+  try {
+    const existingUser = await User.findOne({ email });
+    if (existingUser)
+      return res
+        .status(404)
+        .json({ message: "User with this email already exist." });
+    if (password != confirmPassword) {
+      return res.status(404).json({ message: "Passwords has not confirmed" });
+    }
+
+    
+    const hashedPassword = await bcrypt.hash(password, 12);
+    const result = await User.create({
+      email,
+      password: hashedPassword,
+      name: `${firstName} ${lastName}`,
+    });
+    const token = jwt.sign(
+      { email: result.email, id: result._id },
+      "sometext",
+      {
+        expiresIn: "1h",
+      }
+    );
+
+    profileFields.user = result._id;
+    
+    const profile = await Profile.create(profileFields);
+    await profile.save();
+
+    res.status(201).json({ result, token });
+  } catch (error) {
+    res.status(500).json({ message: "something went wrong" });
+  }
+};
+
+
+

+ 43 - 0
server/index.js

@@ -0,0 +1,43 @@
+import express from "express";
+import mongoose from "mongoose";
+import cors from "cors";
+import dotenv from "dotenv";
+import postsRoutes from "./routes/postsRoutes.js";
+import userRoutes from "./routes/userRoutes.js";
+import getProfilesRoute from "./routes/getProfilesRoute.js";
+import profileRoutes from "./routes/profileRoutes.js";
+
+
+const app = express();
+
+dotenv.config();
+
+app.use(express.json({ limit: "30mb", extended: true }));
+app.use(express.urlencoded({ limit: "30mb", extended: true }));
+app.use(cors());
+
+app.use("/posts", postsRoutes);
+app.use("/auth", userRoutes);
+app.use("/users", getProfilesRoute);
+app.use("/profile", profileRoutes);
+
+app.get('/', (req,res) => {
+  res.send('Hello')
+})
+
+const host = '0.0.0.0';
+// const PORT = process.env.PORT || 5000;
+
+mongoose
+  .connect(process.env.CONNECTION_URL)
+  .then(() =>
+    app.listen(process.env.PORT || 5000,host, () => console.log("Server running on port: " + PORT))
+  )
+  .catch((error) => console.log(error));
+
+//useNewUrlParser, useUnifiedTopology, useFindAndModify,
+//  and useCreateIndex are no longer supported options.
+//   Mongoose 6 always behaves as if useNewUrlParser,
+//    useUnifiedTopology, and useCreateIndex are true,
+//     and useFindAndModify is false.
+//     Please remove these options from your code.

+ 23 - 0
server/middleware/auth.js

@@ -0,0 +1,23 @@
+import jwt from "jsonwebtoken";
+
+const auth = async (req, res, next) => {
+  try {
+    const token = req.headers.authorization.split(" ")[1];
+    const isCustomAuth = token.length < 500;
+
+    let decodedData;
+
+    if (token && isCustomAuth) {
+      decodedData = jwt.verify(token, "sometext");
+      req.userId = decodedData?.id;
+    } else {
+      decodedData = jwt.decode(token);
+      req.userId = decodedData?.sub;
+    }
+    next();
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+export default auth

+ 21 - 0
server/models/postMessage.js

@@ -0,0 +1,21 @@
+import mongoose from "mongoose";
+
+const postSchema = mongoose.Schema({
+  title: String,
+  message: String,
+  name: String,
+  creator: String,
+  selectedFile: String,
+  likes: {
+    type: [String],
+    default: [],
+  },
+  createdAt: {
+    type: Date,
+    default: new Date(),
+  },
+});
+
+const PostMessage = mongoose.model("postmessage", postSchema);
+
+export default PostMessage;

+ 32 - 0
server/models/profile.js

@@ -0,0 +1,32 @@
+import mongoose from "mongoose";
+
+const profileSchema = mongoose.Schema({
+  user: {
+    ref: "user",
+    type: mongoose.Schema.Types.ObjectId,
+  },
+  bio: { type: String, default: "" },
+  age: { type: Number, default: ""},
+  contacts: {
+    youtube: {
+      type: String,
+      default: '',
+    },
+    facebook: {
+      type: String,
+      default: '',
+    },
+    linkedin: {
+      type: String,
+      default: '',
+    },
+    instagram: {
+      type: String,
+      default: '',
+    },
+  },
+});
+
+const Profile = mongoose.model("profile", profileSchema);
+
+export default Profile;

+ 15 - 0
server/models/user.js

@@ -0,0 +1,15 @@
+import mongoose from "mongoose";
+
+const userSchema = mongoose.Schema({
+  name: { type: String, required: true },
+  email: { type: String, required: true },
+  password: { type: String, required: true },
+  id: { type: String},
+  avatar: {type: String, default: ''},
+});
+
+const User = mongoose.model("user", userSchema);
+
+export default User;
+
+

File diff suppressed because it is too large
+ 1654 - 0
server/package-lock.json


+ 35 - 0
server/package.json

@@ -0,0 +1,35 @@
+{
+  "name": "social-network",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "type": "module",
+  "scripts": {
+    "start": "nodemon index.js"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "bcryptjs": "^2.4.3",
+    "body-parser": "^1.19.0",
+    "cors": "^2.8.5",
+    "dotenv": "^10.0.0",
+    "express": "^4.17.1",
+    "jsonwebtoken": "^8.5.1",
+    "mongoose": "^6.0.8"
+  },
+  "devDependencies": {
+    "nodemon": "^2.0.13"
+  },
+  "name": "server",
+  "version": "1.0.0",
+  "main": "index.js",
+  "type": "module",
+  "scripts": {
+    "start": "nodemon index.js"
+  },
+  "keywords": [],
+  "author": "screamoviolence89@gmail.com",
+  "license": "ISC",
+  "description": ""
+}

+ 9 - 0
server/routes/getProfilesRoute.js

@@ -0,0 +1,9 @@
+import  express  from "express";
+import { getProfiles } from "../controllers/profile.js";
+
+const router = express.Router()
+
+router.get('/', getProfiles)
+
+
+export default router

+ 17 - 0
server/routes/postsRoutes.js

@@ -0,0 +1,17 @@
+import  express  from "express";
+import { getPosts, createPost, updatePost, deletePost, likePost } from "../controllers/posts.js";
+import auth from '../middleware/auth.js '
+
+const router = express.Router()
+
+
+router.get('/', getPosts)
+router.post('/', auth, createPost)
+router.patch('/:id',auth, updatePost)
+router.delete('/:id',auth, deletePost)
+router.patch('/:id/likePost',auth, likePost)
+
+
+
+
+export default router

+ 12 - 0
server/routes/profileRoutes.js

@@ -0,0 +1,12 @@
+import  express  from "express";
+import { getProfile, updateProfile } from "../controllers/profile.js";
+import auth from '../middleware/auth.js '
+
+
+const router = express.Router()
+
+router.get('/',auth, getProfile)
+router.patch('/',auth, updateProfile)
+
+
+export default router

+ 11 - 0
server/routes/userRoutes.js

@@ -0,0 +1,11 @@
+ import express from 'express'
+import { signin, signup } from '../controllers/user.js'
+
+
+ const router = express.Router() 
+
+ router.post('/signin', signin)
+ router.post('/signup', signup)
+
+
+ export default router